4

The following correctly parses the text input "2022-12-29 01:16:03 GMT+08:00".

public ZonedDateTime parseZonedDateTime(String timeStr) {
  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss O");

  ZonedDateTime zonedDateTime = ZonedDateTime.parse(timeStr, dtf);

  return zonedDateTime;
}

However, if the input string is "2022-12-29 01:16:03 UTC-08:00", ZonedDateTime.parse() method throws

java.time.format.DateTimeParseException: Text '2022-12-29 01:16:03 UTC-08:00' could not be parsed at index 20

See this code run on Java 12 at Ideone.com.

According to the DateTimeFormatter doc, https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

both "GMT+08:00" and "UTC-08:00" are considered localized zone-offset 'O'.

What should be the correct pattern so that the parser accepts both GMT and UTC inputs?

I have tried using the format "yyyy-MM-dd HH:mm:ss OOOO" but the behavior is the same.

There is a similar question Why does `GMT+8` fail to parse with pattern `O` despite being copied straight out of doc? and according to this, the bug was fixed in Java 9 build b116.

However I'm using java 17.0.4.1-librca

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Leil Jan C
  • 85
  • 8
  • What Locale are you running this in? Have you tried explicitly specifying `Locale.ROOT`? – Joachim Sauer Dec 13 '22 at 16:08
  • I am using the default Locale. I tried explicitly specifying Locale.ROOT but the issue persists. – Leil Jan C Dec 13 '22 at 16:22
  • It works for me, no errors. JDK 17.0.3 oracle. Try another JDK, or post full Junit test, there may be something you don''t see. – pdem Dec 13 '22 at 16:35
  • @pdem I do not see how you did that. Can you copy and run the code [from Ideone.com](https://ideone.com/VZrFmi)? I cannot get it to run on Java 12 nor Java 19. Or paste your code somewhere? – Basil Bourque Dec 18 '22 at 23:11

1 Answers1

5

What should be the correct pattern so that the parser accepts both GMT and UTC inputs?

Use V instead of O i.e. use the pattern, yyyy-MM-dd HH:mm:ss VV.

Demo:

public class Main {
    public static void main(String args[]) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV", Locale.ENGLISH);
        Stream.of(
                "2022-12-29 01:16:03 GMT+08:00",
                "2022-12-29 01:16:03 UTC-08:00"
            )
            .map(s -> ZonedDateTime.parse(s, dtf))
            .forEach(System.out::println);
        ;
    }
}

Output:

2022-12-29T01:16:03+08:00[GMT+08:00]
2022-12-29T01:16:03-08:00[UTC-08:00]

Online Demo

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • How about "2022-07-31 23:48:57 UTC-5"? the "VV" pattern fails on "UTC-5" part. – Leil Jan C Dec 13 '22 at 16:27
  • 2
    @LeilJanC - Unfortunately, when it comes to date parsing, there is nothing like *one size fits all*. You can define a `DateTimeFormatter` using `DateTimeFormatterBuilder` that can work for this variant as well. Let me know if you need help and I will post an update. – Arvind Kumar Avinash Dec 13 '22 at 16:35
  • 3
    @LeilJanC I suggest you educate the publisher of your data about using only [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard formats. And I suggest always expanding an offset to use padding zero, and use both hours and minutes. And not insert `UTC` nor `GMT`. So instead of `UTC-5`, use `-05:00`. While the contraction of hours-only in an offset is allowed under ISO 8601, I have seen multiple libraries not accept such inputs. Best to use expanded format. Example: `OffsetDateTime.parse( "2022-12-29T01:16:03+08:00" )` — easy-peasy. – Basil Bourque Dec 18 '22 at 23:14