1

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?

J-Alex
  • 6,881
  • 10
  • 46
  • 64
user737862
  • 51
  • 8
  • You should share your stacktraces – Mạnh Quyết Nguyễn May 04 '18 at 14:32
  • It seems you’re mimicing the predefined `ISO_LOCAL_DATE_TIME` and giving it the name `ISO_LOCAL_DATE`. That’s confusing. “Local” in `java.time` names means “without time zone or offset”, which may give you a hint. – Ole V.V. May 04 '18 at 16:03
  • Please, what would have been your desired result and why? – Ole V.V. May 04 '18 at 16:09
  • Near-duplicate of [Unable to obtain OffsetDateTime from TemporalAccessor](https://stackoverflow.com/questions/35298214/unable-to-obtain-offsetdatetime-from-temporalaccessor) – Ole V.V. May 04 '18 at 16:40
  • Possible duplicate of [OffsetDateTime parsing](https://stackoverflow.com/questions/38048032/offsetdatetime-parsing) – Ole V.V. May 04 '18 at 16:44

1 Answers1

1

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
J-Alex
  • 6,881
  • 10
  • 46
  • 64
  • Excellent! You're right. But what I actually need is a valid formatter to be used for an OffsetDateTime parser which is out of my reach and I can only set a formatter for it. Is it possible to get a formatter from ZonedDateTime?! Since the ISO_LOCAL_DATE is not valid for OffsetDateTime parser. – user737862 May 04 '18 at 15:35
  • @user737862 Added an example, please refer to the updated answer. – J-Alex May 05 '18 at 00:48
  • @user737862 I may be repeating what is already in the edited answer, but just set the formatter to `DateTimeFormatter.ISO_OFFSET_DATE_TIME`. There’s no reason build your own formatter for it. – Ole V.V. May 06 '18 at 04:17