1

I have below code.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
LocalDateTime myDate =  LocalDateTime.parse("2020-11-16T02:27:39.345Z", formatter);

But it throws below error in the second line. Not sure why it's complaining Z

java.time.format.DateTimeParseException: Text '2020-11-16T02:27:39.345Z' could not be parsed at index 23
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Shabar
  • 2,617
  • 11
  • 57
  • 98
  • 1
    For that date format, either use `"yyyy-MM-dd'T'HH:mm:ss.SSSz"` or `"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"` – ernest_k Nov 16 '20 at 05:35
  • @ernest_k it worked perfectly. Can you please explain reason behind. Probably add as the answer. – Shabar Nov 16 '20 at 06:09
  • 1
    The difference between `Z` and `z` is documented [here](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html). `'Z'` simply makes the parser take the letter literally. – ernest_k Nov 16 '20 at 06:12
  • Does this answer your question? [ZonedDateTime ignores 00 for ss part](https://stackoverflow.com/questions/57325267/zoneddatetime-ignores-00-for-ss-part). Or this? [how to parse OffsetTime for format HHmmssZ](https://stackoverflow.com/questions/59705911/how-to-parse-offsettime-for-format-hhmmssz). – Ole V.V. Nov 18 '20 at 20:28
  • You need to specify no formatter. Just use `Instant.parse("2020-11-16T02:27:39.345Z");` or `OffsetDateTime.parse("2020-11-16T02:27:39.345Z")`. See [this question](https://stackoverflow.com/questions/2597083/illegal-pattern-character-t-when-parsing-a-date-string-to-java-util-date). If you want the time in your local time zone, convert to a `ZonedDateTime`, not a `LocalDateTime`. – Ole V.V. Nov 18 '20 at 20:34
  • @OleV.V. The one mentioned by ernest_k solved the issue. – Shabar Nov 25 '20 at 19:52
  • @SMPH They work. But since you have already experienced that writing a format pattern string is error-prone and challenging — this was why you asked your question — and since the fine answer by Arvind Kumar Avinash shows that you need no format pattern string, why is it that you want to bother? – Ole V.V. Nov 26 '20 at 02:13
  • Also `LocalDateTime` is the wrong class. Your string informs us of a point in time, and a `LocalDateTime` cannot hold a point in time. It’s a bit like storing a `long` value into an `int` variable: a conversion is possible, but you are losing crucial information. – Ole V.V. Nov 26 '20 at 02:16

1 Answers1

3

LocalDateTime does not have timezone or zone-offset information whereas your date-time string has zone-offset. The letter, Z at the end of your date-time string stands for Zulu i.e. zone-offset of UTC. You can parse it into OffsetDateTime or ZonedDateTime or Instant directly (i.e. without using a custom DateTimeFormatter).

Demo:

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        String dateTimeString = "2020-11-16T02:27:39.345Z";
        OffsetDateTime odt = OffsetDateTime.parse(dateTimeString);
        System.out.println(odt);
        ZonedDateTime zdt = ZonedDateTime.parse(dateTimeString);
        System.out.println(zdt);
        Instant instant = Instant.parse(dateTimeString);
        System.out.println(instant);
    }
}

Output:

2020-11-16T02:27:39.345Z
2020-11-16T02:27:39.345Z
2020-11-16T02:27:39.345Z
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110