user737862
user737862

Reputation: 61

Threeten DateTimeParseException for OffsetDateTime.parse(String,dateTimeFormatter)

I would like to simply make a DateTimeFormatter to be used in OffsetDateTime parser. But I get DateTimeParseException:

final DateTimeFormatter ISO_LOCAL_DATE;
ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
    .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
    .appendLiteral('-')
    .appendValue(MONTH_OF_YEAR, 2)
    .appendLiteral('-')
    .appendValue(DAY_OF_MONTH, 2)
    .appendLiteral('T')
    .appendValue(HOUR_OF_DAY,2)
    .appendLiteral(':')
    .appendValue(MINUTE_OF_HOUR,2)
    .appendLiteral(':')
    .appendValue(SECOND_OF_MINUTE,2)
    .toFormatter().withResolverStyle(ResolverStyle.STRICT).withChronology(IsoChronology.INSTANCE);

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
OffsetDateTime.parse("2012-03-06T00:00:00",ISO_LOCAL_DATE);

I looked into one similar issue but there was no clue there either :/ What is the problem with the code above? sth to do with Formatter or Threeten lib?

Upvotes: 2

Views: 742

Answers (1)

J-Alex
J-Alex

Reputation: 7117

You didn't specify an offset in the input data.

This is an example of date-time with offset:

2012-03-06T00:00+01:00

Example of ZonedDateTime:

2012-03-06T00:00+02:00[Europe/Paris]

Europe/Berlin - could be considered as ZoneId here. But each zone may have different offset for different time of the year (summer/winter time).

There is no one-to-one mapping between ZoneId and ZoneOffset: Is there any way to convert ZoneId to ZoneOffset in java 8?

Instead of specifying ZoneOffset you can specify ZoneId and the offset will be determined automatically.

Then you can get ZonedDateTime and convert it to OffsetDateTime.

public OffsetDateTime ZonedDateTime.toOffsetDateTime()

This creates an offset date-time using the local date-time and offset. The zone ID is ignored.

A fix for your case specifying ZoneId:

public class Main {
    private static final DateTimeFormatter ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY,2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR,2)
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE,2)
            .toFormatter()
            .withResolverStyle(ResolverStyle.STRICT)
            .withChronology(IsoChronology.INSTANCE)
            .withZone(ZoneId.systemDefault()); // or whatever you have

    public static void main(String[] args) {
        ZonedDateTime zonedDateTime = ZonedDateTime.parse("2012-03-06T00:00:00", ISO_LOCAL_DATE);
        System.out.println(zonedDateTime);
        System.out.println(zonedDateTime.toOffsetDateTime());
    }
}

Approximate output:

2012-03-06T00:00+01:00[Europe/City]
2012-03-06T00:00+01:00

Second option to fix - add offsetId() to your parser builder and specify offset part for the input string:

public class Main {
    private static final DateTimeFormatter ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
            .appendLiteral('-')
            .appendValue(MONTH_OF_YEAR, 2)
            .appendLiteral('-')
            .appendValue(DAY_OF_MONTH, 2)
            .appendLiteral('T')
            .appendValue(HOUR_OF_DAY,2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR,2)
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE,2)
            .appendOffsetId()
            .toFormatter()
            .withResolverStyle(ResolverStyle.STRICT)
            .withChronology(IsoChronology.INSTANCE);

    public static void main(String[] args) {
        OffsetDateTime offsetDateTime = OffsetDateTime.parse("2012-03-06T00:00:00+02:00", ISO_LOCAL_DATE);
        System.out.println(offsetDateTime);
    }
}

Output:

2012-03-06T00:00+02:00

You can specify your own offset pattern instead of .appendOffsetId() like:

.appendOffset("+HH:mm", "Z")

By the way, there are bunch of standard DateTimeFormatters you can use out-of-the-box to parse OffsetDateTime.

public class Main {
    public static void main(String[] args) {
        String offsetStringTime = "2012-03-06T00:00:00+02:00";
        OffsetDateTime offsetDateTime = OffsetDateTime.parse(offsetStringTime);
        OffsetDateTime offsetDateTime2 = OffsetDateTime.parse(offsetStringTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        OffsetDateTime offsetDateTime3 = OffsetDateTime.parse(offsetStringTime, DateTimeFormatter.ISO_ZONED_DATE_TIME);
        System.out.println(offsetDateTime);
        System.out.println(offsetDateTime2);
        System.out.println(offsetDateTime3);
    }
}

Output:

2012-03-06T00:00+02:00
2012-03-06T00:00+02:00
2012-03-06T00:00+02:00

Upvotes: 2

Related Questions