Understanding Escape characters in Unicode LDML Date Format for extended ISO 8601 - datetime

While using the following control https://openui5.hana.ondemand.com/#docs/api/symbols/sap.m.DatePicker.html#setValueFormat
Supported format options are pattern-based on Unicode LDML Date Format
notation. http://unicode.org/reports/tr35/#Date_Field_Symbol_Table
<DatePicker id="date" value="{/bound/value}" valueFormat="yyyy-MM-dd'T'HH:mm:ss.SSS'Z" displayFormat="MMMM d, y"change="handleChange"/>
In the pattern, the T is escaped with ' on either side.
According to https://www.w3.org/TR/NOTE-datetime, "T" appears literally in the string, to indicate the beginning of the time element, as specified in ISO 8601.
I am confused about the usage pattern for escaping the Z at the end.
Regardless of how I escape the Z with '
on both sides valueFormat="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
or only in the beginning, valueFormat="yyyy-MM-dd'T'HH:mm:ss.SSS'Z",
I still get the correct value.
What is the correct usage here? I would think 'Z' would be more consistent with how 'T' is being escaped.

The Z is not a placeholder like the T. It is a designation of the timezone. If you look in the file you linked it refers to the pattern TZD to represent the designation of the timezone. This may be +1:00 or +11:00 or it may be just Z for Zulu or UTC.
Hopefully that clears it up.
valueFormat="yyyy-MM-dd'T'HH:mm:ss.SSSTZD" is what you are looking for.

Related

ISO datetime with timezone issue

I am just printing the ISO datetime with timezone as per the below documentation
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003169814.htm
This is my code
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-mm-dd'T'hh:mm:ss.nnnnnn+|-hh:mm");
df.setTimeZone(tz);
dateTimeWithTimeZone = df.format(new Date());
However i am getting this exception
Illegal pattern character 'n'
I cant use this format directly in Java ?
java.time
dateTimeWithTimeZone = Instant.now().toString();
System.out.println(dateTimeWithTimeZone);
When I ran this snippet just now, I got this output:
2019-03-18T22:28:13.549319Z
It’s not clear from the page you link to, but it’s an ISO 8601 string in UTC, so should be all that you need. I am taking advantage of the fact that the classes of java.time produce ISO 8601 output from their toString methods. The linked page does show the format with hyphens, T and colons (2008-09-15T15:53:00+05:00), it shows another example with decimals on the seconds (15:53:00.322348) and a third one with Z meaning UTC (20080915T155300Z), so I would expect that the combination of all three of these would be OK too.
The format you used in the quesiton seems to try to get the offset as +00:00 rather than Z. If this is a requirement, it’s only a little bit more complicated. We are using an explicit formatter to control the variations within ISO 8601:
DateTimeFormatter iso8601Formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSSSSxxx");
dateTimeWithTimeZone = OffsetDateTime.now(ZoneOffset.UTC).format(iso8601Formatter);
System.out.println(dateTimeWithTimeZone);
2019-03-18T22:28:13.729711+00:00
What went wrong in your code?
You tried to use the formatting symbols from your source with SimpleDateFormat. First, you should never, and especially not in Java 8 or later, want to use SimpleDateFormat. That class is notoriously troublesome and long outdated. Second, some of its format pattern letters agree with the symbols from your source, some of them don’t, so you cannot just use the symvol string from there. Instead you need to read the documentation and find the correct format pattern letters to use for year, month, etc. And be aware that they are case sensitive: MM and mm are different.
Link
Oracle Tutorial: Date Time
explaining how to use java.time.

Apache Nifi Expression Language - toDate formatting

I am trying to format a date string using the Apache Nifi expression language and the Replace Text processor(regex). Given a date string
date_str : "2018-12-05T11:44:39.717+01:00",
I wish to convert this to:
correct_mod_date_str: "2018-12-05 10:44:39.717",
(notice how the date is converted to UTC, and character 'T' replaced by a space.)
To do this, I am currently using:
toDate("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX"):format("yyyy-MM-dd HH:mm:ss.SSS", '+00:00')
and this works perfectly.
However, when the date string has 6 digits in ms, rather than 3, things break:
another_date_str: "2018-12-05T11:44:39.717456+01:00"
is converted to:
incorrect_mod_date_str: "2018-12-05 10:56:36.456"
It seems the first 3 digits in the ms precision interferes with the conversion.
Appreciate inputs to resolve this - what am I missing?
Regards
seems that's a limitation in java.
according to java documentation there is no support of more then 3 milliseconds digits.
https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
the simplest way is to remove extra digits like this:
attr:replaceAll('(\.\d{3})\d*','$1'):toDate("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"):format("yyyy-MM-dd HH:mm:ss.SSS", '+00:00')
I ran into a similar issue with date time encoded in ISO 8601. The problem is, that the digits after the second are defined as fragment of a second, not milliseconds.
See answer to related topic

Meaning of [Z] in format + string in Moment.js

I am wondering what this does:
newM = moment("2015-08-11T13:00:00.000000Z", "YYYY-MM-DDTHH:mm:ss.SSSS[Z]", true)
Specifically - the [Z] in the format string.
I am using a library (react-bootstrap-datetimepicker) which uses moment. This library (React component) takes a parameter 'format' which is used as the second parameter to moment
I can't see what the [Z] is doing. But I have to do this rather than just 'Z' to get the result I want when I format the moment object for display with this string: newM.format('YYYY-MM-DD HH:mm:ss.SSSZ').
EDIT:
to be clear: I understand that 'Z' will cause the datetime passed to be treated as UTC, as per the docs. But what is the significance of the square brackets - which are not in the docs.
For everyone who cares about consistency due to the missing Z at the end - try to add [Z] to your format.
Example: .format('YYYY-MM-DDTHH:mm:ss[Z]') so the result is: 2019-11-26T10:39:54Z
More detailed explanation you can find in this github issue.
Z does not cause the time to be treated as UTC when used in the format. It matches a timezone specifier:
Format: Z ZZ
Example: +12:00
Description: Offset from UTC as +-HH:mm, +-HHmm, or Z
And under the documentation for format:
To escape characters in format strings, you can wrap the characters in
square brackets.
By specifying Z in brackets, you are matching a literal Z, and thus the timezone is left at moment's default, which is the local timezone.
Unless you specify a time zone offset, parsing a string will create a
date in the current time zone.
If your time is really in UTC, this is probably not desired behavior. If you want to parse it as UTC but display it in local time, use Z and then call local() on the resulting moment object, so most likely what you want is:
// Parse with timezone specifier (which is UTC here) but convert to local time
newM = moment("2015-08-11T13:00:00.000000Z", "YYYY-MM-DDTHH:mm:ss.SSSSZ", true).local();

ASP.NET "String was not recognized as a valid DateTime."

First off, I realize there's a million pages discussing this already. I have looked at least a hundred of them but cannot seem to make this work. My date and time is presented as a string, compiled from javascript to grab client's local time. It is formatted like this: 7/11/2015 8:34 PM.
I currently have:
Dim datetimeformated = DateTime.ParseExact(lblDateTime.Text, "MM/dd/yyyy HH:mm tt", CultureInfo.InvariantCulture)
I have tried many different variants, but this should be correct I think, yet it does not work. Any help is greatly appreciated. TIA
The correct format for your case is: M/dd/yyyy h:mm tt, and perhaps even, M/d/yyyy h:mm tt, if you can have the day of the month as a single digit.
Explanation: Why your format string didn't work.
MM: means that you must always have 2 digits for the month, clearly not the case in your example.
dd: again, means that you must always have 2 digits for the day of the month. Is that the case? Adjust the parameter if needed.
HH: This actually means that you are expecting the hour value as 2-digits using the 24-hour clock (00-23), which is clearly wrong on both accounts. You can have a single digit, and you are not using the 24-hour clock, because you are using the AM/PM designator.
Relevant documentation link: Custom Date and Time Format Strings.

DateTime.TryParseExact does not process long format strings

I have to try and parse out a date time from a string that is causing some trouble.
Most of the time the string will be as follows
'Sat Aug 10 08:01:37 2013'
^ note one space
My original date format for the TryParseExact was 'ddd MMM d HH:mm:ss yyyy'
However, on single digit days, what would normally be the digit in the ten's place is not deleted, but instead it is replaced by a space (see below)
'Wed Aug 7 08:01:37 2013'
^^ note the two spaces
My first idea was to simply remove all the spaces to achieve the format string:
'dddMMMdHH:mm:ssyyyy'
but my DateTime.TryParseExact fails and never accepts the newly formatted (spaceless) format string. Why?
Because with TryParseExact, the spacing of the date is important.
It's a bit hacky, but if no better solution is presented, I would do a TryParseExact using 'ddd MMM d HH:mm:ss yyyy' and if that fails, another TryParseExact using 'ddd MMM d HH:mm:ss yyyy' (with the two spaces)
Edit
I think I found a smarter way, pass DateTimeStyles.AllowInnerWhite to the TryParseExact method.
According to the docs:
Extra white-space characters in the middle of the string must be
ignored during parsing, except if they occur in the DateTimeFormatInfo
format patterns.
Not sure what it means by "except if they occur in the DateTimeFormatInfo format patterns." but it is worth a try.

Resources