6

I have a problem with parsing ZonedDateTime:

DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-ddzhh:mm");
ZonedDateTime.parse(s, formatter);

This results in an error:

java.time.format.DateTimeParseException:
    Text '2022-05-24UTC12:15' could not be parsed at index 10

whats wrong with this code?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
FrancMo
  • 2,459
  • 2
  • 19
  • 39
  • The pattern is wrong… – deHaar May 24 '22 at 12:23
  • Give this a try! [zoneddatetime-parse-method-in-java-with-examples](https://www.geeksforgeeks.org/zoneddatetime-parse-method-in-java-with-examples/) – Mohamad Ghaith Alzin May 24 '22 at 12:43
  • 3
    `2022-05-24UTC12:15` — What a weird format. Is there a particular reason why this format is used? – MC Emperor May 24 '22 at 12:45
  • @MCEmperor well 3rd party has such weird formatting, and are using our API, I was suprised with this format also – FrancMo May 24 '22 at 13:25
  • I cannot reproduce. On my Java 17 I get a completely different exception: `java.time.format.DateTimeParseException: Text '2022-05-24UTC12:15' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {MinuteOfHour=15, HourOfAmPm=0},ISO,Etc/UTC resolved to 2022-05-24 of type java.time.format.Parsed`. – Ole V.V. May 24 '22 at 13:31
  • In your format pattern string you need upper case `HH` for hour of day. See for example [DateTimeParseException: Text '2019-06-07 12:18:16' could not be parsed](https://stackoverflow.com/questions/56500476/datetimeparseexception-text-2019-06-07-121816-could-not-be-parsed). – Ole V.V. May 24 '22 at 13:36
  • What is your locale? Could it be that UTC is called something else in your default locale?? – Ole V.V. May 24 '22 at 13:40
  • Surprise: I can reproduce your problem in German locale even though your formatter still *prints* `UTC` for Etc/UTC time zone. Might look like a bug in java.time (I am still using Java 17). – Ole V.V. May 24 '22 at 13:43
  • I should say it’s a bug. I did a fast search and didn’t find it documented, though. Using German locale `DateTimeFormatter` can parse `2022-05-24UTC` using pattern `yyyy-MM-ddz` and `UTC12:15` using pattern `zHH:mm` but not `2022-05-24UTC12:15` using pattern `yyyy-MM-ddzHH:mm`. With non-German locales there isn’t any problem. Consider reporting it. – Ole V.V. May 24 '22 at 13:55
  • 1
    Yeah, @OleV.V. it's the German locale that was implicitly considered when I tried it without explicitly providing a locale. Works with `Locale.ENGLISH`, for example… – deHaar May 24 '22 at 13:58
  • 1
    For a workaround just specify a non-German locale on your formatter, for example `DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-ddzHH:mm", Locale.ROOT);`. – Ole V.V. May 24 '22 at 13:58
  • 1
    Secondary conclusions still worth noting: (1) It’s always a good idea to specify locale explicitly on your formatter. (2) That 3rd party — and everyone exchanging date and time data — ought to learn about [the ISO 8601 standard for doing so](https://en.wikipedia.org/wiki/ISO_8601). – Ole V.V. May 24 '22 at 14:01

2 Answers2

6

The character z should be able to parse "UTC" (in most Locales) because UTC is considered a time-zone ID and a time-zone name in java.time. A VV can parse time-zone ids while zcan parse time-zone-names according to the JavaDocs of java.time.DateTimeFormatter, here's the relevant part of the docs:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
(…)

V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
z       time-zone name              zone-name         Pacific Standard Time; PST

(…)

That means you can parse it using the character V without providing a specific Locale to your DateTimeFormatter. You will have to put two of them (VV) or you will get a nice IllegalArgumentException with the following message:

java.lang.IllegalArgumentException: Pattern letter count must be 2: V

If you still want to use z, provide a Locale that considers UTC an abbreviation of Universal Time Coordinated, the Central European Summer Time is an abbreviation that definitely changes among different Locales, e.g.

  • English: CEST
  • German: MESZ

Other Locales might have different abbreviations, which makes me wonder if your Locale actually even has a different one for UTC.
Provide Locale.ENGLISH, for example and it should parse successfully.

You should provide one anyway because if you don't, the DateTimeFormatter will implicitly use the default Locale of your (Java Virtual) machine.

So you can try this:

DateTimeFormatter format = DateTimeFormatter.ofPattern("uuuu-MM-ddVVHH:mm");

or this:

DateTimeFormatter format = DateTimeFormatter.ofPattern("uuuu-MM-ddzHH:mm", Locale.ENGLISH);

both should be able to parse an input like "2022-05-24UTC12:15" if you use HH instead of hh for hours of day (hh = 12h format, HH = 24h format).

deHaar
  • 17,687
  • 10
  • 38
  • 51
  • thanks, hmm this works right with UTC, but what if I would like to parse " Text '2022-05-24CEST12:15' could not be parsed at index 10" ? – FrancMo May 24 '22 at 12:40
  • 1
    I want also CEST instead of UTC for example – FrancMo May 24 '22 at 12:40
  • 1
    I think thats why I used z :) but its not good for UTC then – FrancMo May 24 '22 at 12:41
  • 1
    yyyy-MM-ddzHH:mm is perfect then for me – FrancMo May 24 '22 at 12:45
  • I don't think `"2022-05-24CEST12:15"` can be parsed at all with a `DateTimeFormatter` built with a single `z`, at least it doesn't work on my machine. However, `2022-05-24CET12:15` (no `S`, only `CET`) can be parsed with your formatter. – deHaar May 24 '22 at 13:01
  • Yes, @OleV.V. if I apply a `Locale` it will even parse `CEST` ;-), **but not without** and the locales `GERMAN` and `GERMANY` don't work. – deHaar May 24 '22 at 14:00
  • That‘s why it does not work without a locale on my machine… – deHaar May 24 '22 at 14:08
  • 2
    @FrancMo Beware of 2-4 letter pseudo time zones like `CET`, `CEST`, `CST`, `IST`. These are not real time zones, are not standardized, and are not even unique! They should be used only for presentation to the user, never for data exchange. – Basil Bourque May 24 '22 at 19:28
  • 1
    @BasilBourque well I dont like this format but its connected to some 3rd party, thats why. – FrancMo May 25 '22 at 05:20
  • 2
    @FrancMo When you receive such a string with `IST`, how will you know if it means India Standard Time or Ireland Standard time? If you receive a string with `CST`, how will you know if it means Central Standard Time or China Standard Time? – Basil Bourque May 25 '22 at 08:09
-3

Yes it's because of formatter pattern, i suggest to use the code below :

    final DateTimeFormatter format
            = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");

    ZonedDateTime zonedDateTime = ZonedDateTime
            .parse("2022-05-24 14:30:30 -01:00", format);
    
    System.out.println(zonedDateTime);

    ZonedDateTime localTimeline = zonedDateTime
            .withZoneSameInstant(ZoneId.systemDefault());

    // for the local timezone
    System.out.println(localTimeline);
  • 3
    Well, this code won't help the question asker, because their input text is different. – MC Emperor May 24 '22 at 12:46
  • If we want to suggest a different format - which makes sense - I think we should suggest ISO 8601, the international standard. – Ole V.V. May 24 '22 at 20:38