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

3

11

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
Steinberg answered 17/5, 2016 at 22:16 Comment(5)
The fact that this is a StringIndexOutOfBoundsException makes me think this is a bug.Meprobamate
@SotiriosDelimanolis You got it: bugs.openjdk.java.net/browse/JDK-8154050Festinate
Looks like a workaround is to append a space to both the format string and the text to parse.Gauguin
@HankD My experiments show your suggestion of appending a SPACE is indeed a partial workaround for the case of hour-only offset (+08) but not for hour-and-minute offset ( +0800). I edited my Answer to show my experiments using Java 8 Update 92.Steinberg
Leason learned: use a proper ISO timezone offset.Arevalo
F
5

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.

Festinate answered 18/5, 2016 at 1:29 Comment(0)
Z
0

I have the same problem.
My string is something like "28.04.2010 09:39:33 UTC+2".

I have to add a 0 to the offset ("UTC+02"). to get it parsed. As pattern I am using:

   public final static String INPUT_PATTERN_DD_MM_YYYY_HH_mm_ss_zzz = "dd.MM.yyyy HH:mm:ss zzz";

As the offset might be zero ("UTC" or "GMT" without numbers), I am using the DateTimeFormatterBuilder:

   DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive().append(df).optionalStart()
            .appendPattern("X").optionalEnd().toFormatter();

Where "X" is the zone-offset...

But then I also need:

        ZoneId id = ZoneOffset.ofHours(Integer.valueOf(offset));

        zonedDateTime = zonedDateTime.withZoneSameInstant(id);
        zonedDateTime = zonedDateTime.minusHours(Integer.valueOf(offset));

Really awkward... :-(

I hope java 9 will do the right job.

Zeitler answered 26/9, 2016 at 15:33 Comment(0)
A
0

The exact same problem exists with OOOO pattern. That is, when parsing: "Sat May 02 2015 00:00:00 GMT+08:00" with: "EEE MMM dd yyyy HH:mm:ss OOOO" The previous workaround works here as well. That is:

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

Note: The problem is still present in the following JDK 8:

java version "1.8.0_331" 
Java(TM) SE Runtime Environment (build 1.8.0_331-b09) 
Java HotSpot(TM) 64-Bit Server VM (build 25.331-b09, mixed mode) 
Anglomania answered 17/1, 2023 at 22:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.