Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DateTimeFormatterBuilder usages in Java 8, specifically optionals

I'm trying to move from Joda to Java 8's ZonedDateTime and I'm hitting a wall with the DateTimeFormatterBuilder that I cannot seem to work around.

I want to accept any of these formats:

2013-09-20T07:00:33
2013-09-20T07:00:33.123
2013-09-20T07:00:33.123+0000
2013-09-20T07:00:33.123Z
2013-09-20T07:00:33.123Z+0000
2013-09-20T07:00:33+0000

Here is my current builder:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .optionalStart()
        .appendPattern(".SSS")
        .optionalEnd()
        .optionalStart()
        .appendZoneId()
        .optionalEnd()
        .optionalStart()
        .appendPattern("Z")
        .optionalEnd()
        .toFormatter();

I'm probably wrong, but it appears that should match the patterns I want... right?

If anyone could point of what I may have missed, it'd be appreciated. I'm also not too sure of the use of appendOffset, so clarity on that is also appreciated if it turns out to be the answer.

Edit:

Text '2013-09-20T07:00:33.061+0000' could not be parsed at index 23

Looking at the builder, this appears to match due to the optional stages?

Edit 2:

After seeing advice from the first answer, I tried this:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        .optionalStart()
        .appendPattern(".SSS")
        .optionalEnd()
        .optionalStart()
        .appendZoneOrOffsetId()
        .optionalEnd()
        .toFormatter()

It continues to fail on the string above.

Edit 3:

Latest tests result in this exception:

java.time.format.DateTimeParseException: Text '2013-09-20T07:00:33.061+0000' could not be parsed at index 23
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:582)
like image 774
whitfin Avatar asked Apr 17 '15 23:04

whitfin


People also ask

What is date-time formatter in Java?

Represents a time (hour, minute, second and nanoseconds (HH-mm-ss-ns)) LocalDateTime. Represents both a date and a time (yyyy-MM-dd-HH-mm-ss-ns) DateTimeFormatter. Formatter for displaying and parsing date-time objects.

What is DateTimeFormatter?

public final class DateTimeFormatter extends Object. Formatter for printing and parsing date-time objects. This class provides the main application entry point for printing and parsing and provides common implementations of DateTimeFormatter : Using predefined constants, such as ISO_LOCAL_DATE.

Is Java time format DateTimeFormatter thread-safe?

Yes, it is: DateTimeFormat is thread-safe and immutable, and the formatters it returns are as well.

Which time format is followed in Java 8?

For time patterns, use mm for two-digit minute and ss for two-digit second. The hh pattern generates the two-digit hour for a 12-hour clock (e.g., 6PM is "06") and HH generates the two-digit hour for a 24-hour clock (e.g., 6PM is "18").


1 Answers

It may be the reason that +0000 is not a zone id, but a zone offset.

the documentation offers this list:

  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
       O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
       X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
       x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
       Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

You may use appendOffset("+HHMM", "0000") (doc) or appendZoneOrOffsetId() (doc) instead of appendZoneId().

so your full formatter may look like the following

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
                .optionalStart()
                .appendPattern(".SSS")
                .optionalEnd()
                .optionalStart()
                .appendZoneOrOffsetId()
                .optionalEnd()
                .optionalStart()
                .appendOffset("+HHMM", "0000")
                .optionalEnd()
                .toFormatter();

Further the way of creating a ZonedDateTime may influence if there is an exception or not. Therefore I'd recommend the following as this worked without any exceptions.

LocalDateTime time = LocalDateTime.parse("2013-09-20T07:00:33.123+0000", formatter);
ZonedDateTime zonedTime = time.atZone(ZoneId.systemDefault());
like image 90
sailingthoms Avatar answered Sep 22 '22 18:09

sailingthoms