6

I have the following tests.

@Test
void withoutColon_fails() {
    ZonedDateTime.parse("2019-01-24T12:10:58.036820+0400");
}

@Test
void withColon_ok() {
    ZonedDateTime.parse("2019-01-24T12:10:58.036820+04:00");
}

The only difference between the date-times I'm trying to parse is that in the first case there is no colon between hours and minutes in timezone designation, and in the second case there is a colon.

First of them fails:

java.time.format.DateTimeParseException: Text '2019-01-24T12:10:58.036820+0400' could not be parsed, unparsed text found at index 29

    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2049)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:598)
    at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:583)

According to the javadoc, parse(), through DateTimeFormatter.ISO_ZONED_DATE_TIME, eventually uses DateTimeFormatter.ISO_OFFSET_DATE_TIME, on which, in turn, we can read that it is

The ISO date-time formatter that formats or parses a date-time with an offset, such as '2011-12-03T10:15:30+01:00'.

Following the javadoc links further, we get to ZoneOffset.getId() which says that it accepts:

Z - for UTC (ISO-8601)
+hh:mm or -hh:mm - if the seconds are zero (ISO-8601)
+hh:mm:ss or -hh:mm:ss - if the seconds are non-zero (not ISO-8601)

So, the colon is always mandatory, according to the javadocs.

But, according to https://en.wikipedia.org/wiki/ISO_8601 ,

The UTC offset is appended to the time in the same way that 'Z' was above, in the form ±[hh]:[mm], ±[hh][mm], or ±[hh].

So the colon is NOT mandatory, according to the standard, and it seems that Java does not support the standard completely.

The question is: why? Was the omission deliberate, is there a good reason for this?

This works this way in both Java 8 and Java 11.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Roman Puchkovskiy
  • 11,415
  • 5
  • 36
  • 72
  • 5
    Basically it's parsing the most common ISO-8601 representation, but not every possible representation. (I suspect it wouldn't parse 20190124T121058+04:00 either, although that's valid ISO-8601 too.) If you need to support both, it shouldn't be too hard to `DateTimeFormatterBuilder` to construct the appropriate formatter. I *would* recommend that you use `OffsetDateTime` instead of `ZonedDateTime` if you're only ever given an offset though (rather than an actual time zone). That way you'd be more accurately representing what the text says. – Jon Skeet Jan 24 '20 at 11:27
  • We are some who have wondered. At a time I was hoping it was a bug in Java 8, but it wasn’t fixed in Java 9. :-( (@JonSkeet is completely correct.) – Ole V.V. Jan 24 '20 at 17:32
  • There are many examples of ISO 8601 format variants that the java.time classes neither parse nor print (from `toString()`). The offset without the colon is the most often noted one. Here’s a quote diffrerent example: [DateTimeParseException at index 0 with ThreeTenABP](https://stackoverflow.com/questions/59781056/datetimeparseexception-at-index-0-with-threetenabp) (ThreeTenABP is the Android adaptation of the backport of java.time to Java 6 and 7; the issue described is the same in Java 8+). – Ole V.V. Jan 25 '20 at 06:08
  • 2
    While it is true that `java.time` does not support all ISO-8601-variants, your and Jon Skeets assumption that "2019-01-24T12:10:58.036820+0400" shall be valid ISO is wrong because you are mixing basic (in the offset part) and extended format which is explicitly prohibited in ISO-paper (see sections 4.3.2 and 4.3.3d). – Meno Hochschild Jan 31 '20 at 16:52
  • Thank you @MenoHochschild! I've upvoted your answer in the linked question. – Roman Puchkovskiy Mar 23 '20 at 13:02

0 Answers0