Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `GMT+8` fail to parse with pattern `O` despite being copied straight out of doc?

Why does the following fail to run, with the date-time string unable to parse as an OffsetDateTime?

String inputOdt = "2016-01-23T12:34:56 GMT+8";
DateTimeFormatter formatterOdt = DateTimeFormatter.ofPattern ( "yyyy-MM-dd'T'HH:mm:ss O" );
OffsetDateTime odt = OffsetDateTime.parse ( inputOdt , formatterOdt );

Using Java(TM) SE Runtime Environment (build 1.8.0_92-b14) on Mac OS X El Capitan 10.11.4.

Generates error:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2016-01-23T12:34:56 GMT+8' could not be parsed: String index out of range: 25

The offset-from-UTC string GMT+8 is copied-pasted from the example in the class documentation for DateTimeFormatter. To quote:

Offset O: This formats the localized offset based on the number of pattern letters. One letter outputs the short form of the localized offset, which is localized offset text, such as 'GMT', with hour without leading zero, optional 2-digit minute and second if non-zero, and colon, for example 'GMT+8'.


The rest of the string parses successfully as a LocalDateTime. So the problem seems to indeed be the offset-from-UTC part.

String inputLdt = "2016-01-23T12:34:56";
DateTimeFormatter formatterLdt = DateTimeFormatter.ofPattern ( "yyyy-MM-dd'T'HH:mm:ss" );
LocalDateTime ldt = LocalDateTime.parse ( inputLdt , formatterLdt );

System.out.println ( "" );
System.out.println ( "inputLdt: " + inputLdt );
System.out.println ( "ldt: " + ldt );

inputLdt: 2016-01-23T12:34:56

ldt: 2016-01-23T12:34:56


Workaround

A partial workaround is to add a trailing SPACE to both the input string and the formatting pattern. So this works.

String input = "Sat May 02 2015 00:00:00 GMT+08 "; // Trailing space.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM dd yyyy HH:mm:ss O " ); // Trailing space.
OffsetDateTime odt = OffsetDateTime.parse ( input , formatter ); // SUCCEEDS

But adding minutes without a colon is documented as working with a single O but it fails. This workaround of a trailing SPACE does not help in such a case. Notice the GMT+0800 in this example versus GMT+08 seen directly above, where this example fails but the one above succeeds.

String input = "Sat May 02 2015 00:00:00 GMT+0800 "; // Minutes in the offset, and trailing space.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM dd yyyy HH:mm:ss O " ); // Trailing space.
OffsetDateTime odt = OffsetDateTime.parse ( input , formatter ); // FAILS
like image 949
Basil Bourque Avatar asked May 17 '16 22:05

Basil Bourque


1 Answers

Seems to be a bug in Java. See https://bugs.openjdk.java.net/browse/JDK-8154050:

java.time.format.DateTimeFormatter can't parse localized zone-offset

The DateTimeFormatter fails to parse its own output for format strings containing "O". The following code throws a StringIndexOutOfBoundsException on the final line.

import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter
        .ofPattern("yyyy-MM-dd'T'HH:mm:ss.S O")
        .withLocale(Locale.ENGLISH)
String date = formatter.format(ZonedDateTime.now(ZoneOffset.UTC));
formatter.parse(date)

ERROR MESSAGES/STACK TRACES THAT OCCUR : java.time.format.DateTimeParseException: Text '2016-04-08T10:49:52.7 GMT' could not be parsed: String index out of range: 25

And in a comment:

Attached test case executed on:
JDK 8 - Fail
JDK 8u77 - Fail
JDK 9EA - Fail

Seems it was fixed in Java 9 build b116.

like image 86
Andreas Avatar answered Oct 24 '22 12:10

Andreas