DateTime Madness?

Moin,

folgendes Problem: Aus einem String mit ISO 8601 Datum und Zeit ein java.util.Date machen.
Schwierigkeit: String kann mit oder ohne Zeitzone / Offset sein. Ich will also eine Zeitzone
vorgeben können, wenn im String keine vorhanden ist.

Erster Versuch war mit DateTimeFormatter.ISO_OFFSET_DATE_TIME, der wirft aber eine Exception
wenn der Offset keinen Doppelpunkt enthält.

Also versucht selbst einen DateTimeFormatter zu bauen.

import java.sql.Date;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;

public class IsoTimeTest {
  public static void main(String[] args) {
    parse(
      "2015-01-28T16:59:58",
      "2015-01-28T16:59:58.212",
      "2015-01-28T16:59:58.212+0500",
      "2015-01-28T16:59:58.212+05:00",
      "2015-01-28T16:59:58.212+05",
      "2015-01-28T16:59:58+05:00",
      "2015-01-28T16:59:58+0500",
      "2015-01-28T16:59:58+05"
    );
  }

  public static void parse(String... dates) {
    Arrays.stream(dates).forEach((d) -> {
      System.out.print("Zoned ");
      IsoTimeTest.parseWithZoned(d);
    });


    Arrays.stream(dates).forEach((d) -> {
      System.out.print("Offset ");
      IsoTimeTest.parseWithOffset(d);
    });
  }

  public static void parseWithZoned(String date) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS][XXX][XX][X]").withZone(ZoneId.of("Europe/Berlin"));
    try {
      ZonedDateTime zdt = ZonedDateTime.parse(date, formatter);
      System.out.println("OK:  " + date + " -- " + Date.from(zdt.toInstant()));
    } catch (Exception e) {
      System.out.println("NOK: " + date + " -- " + e.getMessage());
    }
  }

  public static void parseWithOffset(String date) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS][XXX][XX][X]").withZone(ZoneId.of("Europe/Berlin"));
    try {
      OffsetDateTime zdt = OffsetDateTime.parse(date, formatter);
      System.out.println("OK:  " + date + " -- " + Date.from(zdt.toInstant()));
    } catch (Exception e) {
      System.out.println("NOK: " + date + " -- " + e.getMessage());
    }
  }
}

Zoned OK:  2015-01-28T16:59:58 -- Wed Jan 28 16:59:58 CET 2015
Zoned OK:  2015-01-28T16:59:58.212 -- Wed Jan 28 16:59:58 CET 2015
Zoned OK:  2015-01-28T16:59:58.212+0500 -- Wed Jan 28 16:59:58 CET 2015
Zoned OK:  2015-01-28T16:59:58.212+05:00 -- Wed Jan 28 16:59:58 CET 2015
Zoned OK:  2015-01-28T16:59:58.212+05 -- Wed Jan 28 16:59:58 CET 2015
Zoned OK:  2015-01-28T16:59:58+05:00 -- Wed Jan 28 16:59:58 CET 2015
Zoned OK:  2015-01-28T16:59:58+0500 -- Wed Jan 28 16:59:58 CET 2015
Zoned OK:  2015-01-28T16:59:58+05 -- Wed Jan 28 16:59:58 CET 2015
Offset NOK: 2015-01-28T16:59:58 -- Text '2015-01-28T16:59:58' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1422460798},ISO,Europe/Berlin resolved to 2015-01-28T16:59:58 of type java.time.format.Parsed
Offset NOK: 2015-01-28T16:59:58.212 -- Text '2015-01-28T16:59:58.212' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1422460798},ISO,Europe/Berlin resolved to 2015-01-28T16:59:58.212 of type java.time.format.Parsed
Offset OK:  2015-01-28T16:59:58.212+0500 -- Wed Jan 28 12:59:58 CET 2015
Offset OK:  2015-01-28T16:59:58.212+05:00 -- Wed Jan 28 12:59:58 CET 2015
Offset OK:  2015-01-28T16:59:58.212+05 -- Wed Jan 28 12:59:58 CET 2015
Offset OK:  2015-01-28T16:59:58+05:00 -- Wed Jan 28 12:59:58 CET 2015
Offset OK:  2015-01-28T16:59:58+0500 -- Wed Jan 28 12:59:58 CET 2015
Offset OK:  2015-01-28T16:59:58+05 -- Wed Jan 28 12:59:58 CET 2015

Hmm, ZonedDateTime frisst zwar alles, aber der Offset wird einfach mal ignoriert, wenn vorhanden.
Das kommt mir völlig kaputt vor, warum sollte man jemals einen vorhandenen Offset überschreiben?.

Mit OffsetDateTime ist das Ergebnis noch absurder, er wirft eine Exception, obwohl er alle Infos
hat um den Offset berechnen zu können.

Macht das für irgendjemanden Sinn?

Sorry, keine wirklich konkrete Hilfe…: Bei kurzem Blick über den Code schaut es für mich (!) im Moment (!) so aus, als MÜSSTE der “Offset” immer in einem bestimmten Format sein (entweder mit oder ohne Doppelpunkt) - aber ggf. muss ich nochmal schauen, wie die Patterns da tatsächlich verarbeitet werden (das ganze ist ziemlich kompliziert). Bei solchen Sachen habe ich persönlich dann die Tendenz, dem Aufrufer zu sagen: “Sieh’ zu, dass das, was du mir gibst, auch passt (und füg’ ggf. einen Doppelpunkt in deinen Offset ein)” - aber das ist natürlich nicht immer anwendbar.