简体   繁体   中英

LocalDateTime format with time zone and milliseconds

I'm trying to write a DateTimeFormatter to parse the following format:

2020-05-29T07:51:33.106-07:00

I have looked at ISO_OFFSET_DATE_TIME , but the problem is it does not contain milliseconds. So I decided to write on my own.

It is easy to do so without timezone:

public static void main (String[] args) throws java.lang.Exception {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
    System.out.println(
        LocalDateTime.parse("2020-05-29T07:51:33.106", formatter)
    );
}

It works just fine

But when I tried to add a timezone in the format as

public static void main (String[] args) throws java.lang.Exception {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    System.out.println(
        LocalDateTime.parse("2020-05-29T07:51:33.106-07:00", formatter)
    );
}

It now fails with an exception that the timezone is unable to be parsed.

Exception in thread "main" java.time.format.DateTimeParseException: Text '2020-05-29T07:51:33.106-07:00' could not be parsed at index 23
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2049)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1951)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at Ideone.main(Main.java:16)

How to parse a timezone in such a format?

tl;dr

No need to define a formatter.

OffsetDateTime.parse( "2020-05-29T07:51:33.106-07:00" )

Details

The Answer by Jim Garrison is correct. In addition, you are using the wrong class.

The LocalDateTime class represents only a date with a time-of-day, nothing more. This class purposely lacks any concept of time zone or offset-from-UTC. As such, this class cannot represent a moment, is not a point on the timeline.

在此处输入图像描述

So, parsing a string with an offset, the -07:00 on the end, as a LocalDateTime does not make sense. The valuable information of offset will be ignored, discarded.

Instead, parse as an OffsetDateTime .

Bonus: Your entire formatter issue becomes moot. Your input string complies with the standard ISO 8601 format used by default in the OffsetDateTime class when parsing/generating strings. No need for you to define any custom formatting pattern at all.

OffsetDateTime.parse( "2020-05-29T07:51:33.106-07:00" )

…and:

myOffsetDateTime.toString() 

You said:

But when I tried to add a timezone

No, you added an offset-from-UTC, not a time zone, with your string -07:00 .

  • An offset is merely a number of hours-minutes-seconds ahead or behind the prime meridian.
  • A time zone is much more. A time zone has a name such as America/Edmonton . A time zone has a history of the past, present, and future changes to the offset in the wall-clock time used by the people of a particular region.

From the Javadoc (emphasis mine):

Offset Z: This formats the offset based on the number of pattern letters. 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. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.

Change the single Z to ZZZZZ .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM