4

I'm new to java and I'm not understanding what's wrong with my date parsing. I've tried many of the solutions to similar posts, read the DateTimeFormatter documentation and am still stuck. Any help is appreciated. Thank you.

Code

String date = "2021-02-19T00:45:09.798Z"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSZ");
ZonedDateTime parsedDate = ZonedDateTime.parse(date, formatter);

Error

java.time.format.DateTimeParseException: Text '2021-02-19T00:45:09.798Z' could not be parsed, unparsed text found at index 23

I've also tried using DateTimeFormatter.ofPattern(pattern).withZone(zone) and receive the same error.

Michael
  • 41,989
  • 11
  • 82
  • 128
zzzhw3137
  • 97
  • 1
  • 7

2 Answers2

12

You do not need a formatter to parse the given date-time string as it's already compliant with the default format that ZoneDateTime#parse expects.

import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        String date = "2021-02-19T00:45:09.798Z";
        ZonedDateTime parsedDate = ZonedDateTime.parse(date);
        System.out.println(parsedDate);
    }
}

Output:

2021-02-19T00:45:09.798Z

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


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • 3
    Since there is no time zone present, I would use `Instant` or `OffsetDateTime` here rather than `ZonedDateTime`. – Basil Bourque Mar 02 '21 at 16:34
  • @BasilBourque Technically, `Z` is the Zulu timezone, which is a synonym for GMT. – VGR Mar 02 '21 at 16:35
  • 2
    @VGR UTC/Zulu is *not* actually a time zone. It is the baseline against which all time zones are defined. That is why the *java.time* provides the `Instant` and `OffsetDateTime` classes separate from `ZonedDateTime`, and why the constant `UTC` is defined on the `ZoneOffset` class rather than on the `ZoneId` class. An offset is merely a number of hours-minutes-seconds, positive or negative. A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by he people of a particular region. So for this Answer, `ZonedDateTime` is inappropriate. – Basil Bourque Mar 02 '21 at 16:57
  • 2
    To be fair, there's also `DateTimeFormatter.ISO_INSTANT` which supports `Z` and Z only, expecting an Instant, always. So depending on what kinds of input OP actually expects, an `Instant` could be a choice (next to `ZonedDateTime` and `OffsetDateTime`), I do not think we can really tell from the single available input. But: Z _usually_ means offset, not ZoneId, even though it's a fine ZoneId, too. – Petr Janeček Mar 02 '21 at 17:00
5

Index 23 of your input is Z, the time offset indicator. And indeed, if we look at the formatting patterns docs, we see the "Z" as a pattern for offsets with:

Offset Z: [...] One, two or three letters outputs the hour and minute, without a colon, such as '+0130'. The output will be '+0000' when the offset is zero.

, and "X" as a pattern for offsets while using 'Z' for zero:

Offset X: [...] Pattern letter 'X' (upper case) will output 'Z' when the offset to be output would be zero . Therefore, this works:

DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX")

That said, if your input is in a well-known ISO 8601 standard format, you might want to use one of the predefined formatters instead, like ISO_OFFSET_DATE_TIME (or some other, depending on your input's ZoneId/offset usage).

Petr Janeček
  • 37,768
  • 12
  • 121
  • 145