Some Name
Some Name

Reputation: 9521

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?

Upvotes: 5

Views: 7656

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338171

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.

enter image description here

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.

Upvotes: 6

Jim Garrison
Jim Garrison

Reputation: 86744

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.

Upvotes: 8

Related Questions