2016-11-10 4 views
6

Es ist mein Verständnis, dass eine ZonedDateTime ist wirklich eine erweiterte Version von Instant. Es hat alle Daten, die ein Instant hat (genauer Wert entlang der UTC-Zeitachse), plus Zeitzoneninformationen. Also meine naive Annahme war, dass ein ist-einInstant und dass jede Methode, die eine Instant nimmt glücklich statt ZonedDateTime statt. Darüber hinaus erwartete ich isBefore(), isAfter() etc. nahtlos zwischen Instant s und ZonedDateTime s zu arbeiten.Kompatibilität zwischen Instant und ZonedDateTime

Wenn Sie die API-Dokumentation für Instant und ZonedDateTime betrachten, ist das alles nicht der Fall. Ich kann Instant s mit Instant s und ZonedDateTime s mit ZonedDateTime s vergleichen, aber die zwei Klassen scheinen inkompatibel zu sein. Darüber hinaus scheint Code von Drittanbietern wie ThreeTen-Extra Interval ausschließlich mit Instant s zu arbeiten.

Gibt es einen Grund, warum Instant und ZonedDateTime nicht zum Mischen gedacht sind?

+0

Nun, sagt die Dokumentation deutlich, dass es gesehen werden soll, eine 'LocalDateTime', die mit einer Zone verbunden ist, notieren Sie sich als' Instant', gekoppelt mit einer Zone. Es enthält alle Datums- und Uhrzeitfelder, keinen Offset von einem Punkt in UTC. Warum erwarten Sie, dass es sich anders verhält als seine Dokumentation sagt? – RealSkeptic

+0

Sie können ein 'ZonedDateTime' in ein' Instant' mit ['.toInstant()'] (http://docs.oracle.com/javase/8/docs/api/java/time/chrono/ChronoZonedDateTime.html) konvertieren # toInstant--), aber um von einem 'Instant' in ein' ZonedDateTime' zu ​​konvertieren, müssen Sie ['ZonedDateTime.ofInstant'] (http://docs.oracle.com/javase/8/docs/api/java /time/ZonedDateTime.html#ofInstant-java.time.Instant-java.time.ZoneId-) und geben Sie eine 'ZoneId' an. – Powerlord

Antwort

5

Weil die Übersetzung nicht injektiv ist. Nehmen Sie Sonntag, 30. Oktober 2016 2:15 Uhr in Deutschland/München zum Beispiel: Welche Instant steht dieses Datum/Zeit? Dies ist nicht unabhängig ohne einige Annahmen zu beantworten, weil Sie nicht wissen, ob diese Zeit in die Instantvor oder nach der Offset für Sommerzeit (DST) sollte umgesetzt werden soll übersetzt werden. Oder Sonntag, 27. März 2016 2:15 Uhr in Deutschland/München: Diese Datum/Uhrzeit-Kombination sollte nicht existieren, da die Uhr bei Erreichen von 2 Uhr auf 3 Uhr morgens eingestellt werden sollte.

Ohne DST die drei möglichen Fälle für eine LocalDateTime in eine Instant (genaue Übereinstimmung, Sommerzeit-gap, Winterzeit-Überlappung) übersetzen würde auf einen reduziert werden, und die Umwandlung wäre injektive, AFAIK.

Edit: "Hands on" dieses Problem, wenn Datum/Uhrzeit in unserer JSF-basierten Anwendung anzeigen, übergeben wir immer übergeben Sie den Offset berechnet entsprechend dem aktuellen Zustand der Sommerzeit in den Formatierer.

+0

Der ZonedDateTime-Dokumentstatus: "Diese Klasse speichert ... einen Zonenoffset, der zum Behandeln mehrdeutiger lokaler Datumsangaben verwendet wird." Bedeutet das nicht, dass es eine eindeutige Zuordnung von "ZonedDateTime" zu "Instant" gibt? –

5

Instant und ZonedDateTime haben unterschiedlichen Zustand - Instant ist nur eine Zahl von Nanosekunden aus der Epoche, während ZonedDateTime einen LocalDateTime, ZoneId und ZoneOffset besteht. Daher können die beiden Klassen ineinander konvertiert werden, sind aber nicht identisch (und Sie verlieren Informationen, wenn Sie ZonedDateTime in Instant konvertieren). Das Verhalten von isBefore() und isAfter() stimmt genau zwischen den beiden überein. Während die Implementierung von Comparable dem empfohlenen Verhalten entspricht, das heißt: "Es wird dringend empfohlen (obwohl nicht erforderlich), dass natürliche Ordnungen konsistent mit Gleichen sind." dh. compareTo() berücksichtigt das lokale Datum-Zeit, Zeitzone und Offset, während isBefore() und isAfter() nur den Augenblick betrachten.

ein Komparator Schreiben ein Instant und ZonedDateTime zu vergleichen, ist relativ einfach:

Comparator<TemporalAccessor> comparator = 
    (a, b) -> Instant.from(a).compareTo(Instant.from(b)); 

, die auch als geschrieben werden kann:

Comparator<TemporalAccessor> comparator = Comparator.comparing(Instant::from); 
Verwandte Themen