I am using following ISO8601 format:
YYYY-MM-DDThh:mm:ssZ
And I used OffsetDateTime.parse()
to parse this format. I was able to parse date-time by passing t
(instead of T
) and z
(instead of Z
) here.
So can anyone tell if it is allowed in ISO8601 or is it missed only in parsing logic?
So can anyone tell if it is allowed in ISO8601 or is it missed only in parsing logic?
I don't think it's valid to produce them though I guess it's fine (though not great) that the parser allows it.
The normative EBNF I have access to (8601-1 DIS Annex A) uses only uppercase latin letter for all designators, whether they be Z, T, W, R, P, Y, M, D, H, M, or S, and unlike (non-A) BNF, as far as I know EBNF terminals are case sensitive.
Z
is not the same as z
.DateTimeFormatter
evaluates the former as zone-offset while the later as time-zone name.
Another example can be M
which it uses for month-of-year, and m
which it uses for minute-of-hour.
The symbol for the components of date, time, timezone etc. are case-sensitive. Check DateTimeFormatter
to learn more about these symbols.
A quick demo:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
ZonedDateTime odt = ZonedDateTime.now(ZoneId.of("Asia/Calcutta"));
System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ").format(odt));
System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssz").format(odt));
}
}
Output:
2020-12-22T00:14:44+0530
2020-12-22T00:14:44IST
A zone offset is not the same as timezone. A timezone has an ID in the form, Continent/City
e.g. Asia/Calcutta
whereas a zone offset is represented in hours and minutes which tells how many hours and minutes the date & time of a place is offset from UTC
date & time. Thus, many timezone IDs can have the same zone offset. In other words, a zone offset can be derived from the timezone ID but the converse is not possible e.g. in the following demo, OffsetDateTime
will be able to determine the zone offset from the timezone ID of Asia/Calcutta
but trying to get the timezone name (as in the above example) using z
will fail.
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.now(ZoneId.of("Asia/Calcutta"));
System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ").format(odt));
System.out.println(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssz").format(odt));
}
}
Output:
2020-12-22T00:30:40+0530
Exception in thread "main" java.time.DateTimeException: Unable to extract ZoneId from temporal 2020-12-22T00:30:40.865087+05:30
at java.base/java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:289)
at java.base/java.time.format.DateTimeFormatterBuilder$ZoneTextPrinterParser.format(DateTimeFormatterBuilder.java:4072)
at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2341)
at java.base/java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1843)
at java.base/java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1817)
at Main.main(Main.java:9)
And I used "OffsetDateTime.parse()" (in java) to parse this format. I was able to parse date time by passing "t" (instead of "T") and "z" (instead of "Z") here.
I have already explained about Z
and z
. Let's focus on T
and t
. If you observe carefully, you will find that I've used single quotes around T
i.e. 'T'
which makes it a string literal to be used inside the date-time string. It means that it can be anything e.g. 't'
or 'Foo'
or 'Bar'
. As long as the literals in the DateTimeFormatter
matches in the same case with that in the date-time string, it works without any problem. I've shown it in the following demo:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String strDateTime = "2020-12-22T00:45:50+05:30";
// The given string is already in the format which is use by OffsetDateTime for
// parsing without a DateTimeFormatter
OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
// Let's try to parse it using different types of DateTimeFormatter instances
System.out.println(OffsetDateTime.parse(strDateTime, DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX")));
//The following line will fail as the literal does not match case-wise
//System.out.println(OffsetDateTime.parse(strDateTime, DateTimeFormatter.ofPattern("uuuu-MM-dd't'HH:mm:ssXXX")));
strDateTime = "2020-12-22t00:45:50+05:30";// Now, DateTimeFormatter with 't' will work successfully
System.out.println(OffsetDateTime.parse(strDateTime, DateTimeFormatter.ofPattern("uuuu-MM-dd't'HH:mm:ssXXX")));
}
}
Output:
2020-12-22T00:45:50+05:30
2020-12-22T00:45:50+05:30
Learn more about the modern date-time API from Trail: Date Time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With