Ich habe die Dokumentation gelesen, kann aber immer noch nicht herausfinden, wann ich das eine oder andere verwenden soll:
Laut Dokumentation OffsetDateTime
sollte beim Schreiben von Datum in die Datenbank verwendet werden, aber ich verstehe nicht warum.
F: Was ist der Unterschied zwischen Java 8 ZonedDateTime und OffsetDateTime?
Die Javadocs sagen dazu:
“OffsetDateTime
, ZonedDateTime
und Instant
alle speichern einen Moment auf der Zeitachse mit Nanosekunden-Präzision. Instant
ist die einfachste und repräsentiert einfach den Augenblick. OffsetDateTime
fügt dem Moment den Offset von UTC/Greenwich hinzu, wodurch die lokale Datumszeit erhalten werden kann. ZonedDateTime
fügt vollständige Zeitzonenregeln hinzu.”
Quelle: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html
Also der Unterschied zw OffsetDateTime
und ZonedDateTime
ist, dass letzteres die Regeln enthält, die Sommerzeitanpassungen und verschiedene andere Anomalien abdecken.
Einfach gesagt:
Zeitzone = ( Versatz von UTC + Regeln-für-Anomalien )
F: Laut Dokumentation OffsetDateTime
sollte beim Schreiben von Datum in die Datenbank verwendet werden, aber ich verstehe nicht warum.
Datumsangaben mit Ortszeitversatz stellen immer die gleichen Zeitpunkte dar und haben daher eine stabile Reihenfolge. Dagegen ist die Bedeutung von Datumsangaben mit vollständiger Zeitzonenangabe angesichts von Anpassungen der Regeln für die jeweiligen Zeitzonen instabil. (Und diese passieren; z. B. für Datum-Zeit-Werte in der Zukunft.) Wenn Sie also a speichern und dann abrufen ZonedDateTime
Die Implementierung hat ein Problem:
-
Es kann den berechneten Offset speichern … und das abgerufene Objekt kann dann einen Offset haben, der nicht mit den aktuellen Regeln für die Zonen-ID übereinstimmt.
-
Es kann den berechneten Offset verwerfen … und das abgerufene Objekt stellt dann einen anderen Punkt in der absoluten / universellen Zeitachse dar als den, der gespeichert wurde.
Wenn Sie die Java-Objektserialisierung verwenden, wählt die Java 9-Implementierung den ersten Ansatz. Dies ist wohl der “korrektere” Weg, damit umzugehen, aber dies scheint nicht dokumentiert zu sein. (JDBC-Treiber und ORM-Bindungen treffen vermutlich ähnliche Entscheidungen und machen es hoffentlich richtig.)
Aber wenn Sie eine Anwendung schreiben, die Datums-/Uhrzeitwerte manuell speichert oder sich auf java.sql.DateTime
, dann ist der Umgang mit den Komplikationen einer Zonen-ID … wahrscheinlich etwas, das vermieden werden sollte. Daher der Rat.
Beachten Sie, dass Daten, deren Bedeutung / Reihenfolge im Laufe der Zeit instabil ist vielleicht problematisch für eine Bewerbung. Und da Änderungen an Zonenregeln ein Grenzfall sind, treten die Probleme wahrscheinlich zu unerwarteten Zeiten auf.
Ein (möglicher) zweiter Grund für die Beratung ist, dass die Konstruktion von a ZonedDateTime
ist an bestimmten Stellen zweideutig. In der Zeit, in der Sie beispielsweise die Uhren zurückstellen, können Sie durch die Kombination einer Ortszeit und einer Zonen-ID zwei verschiedene Offsets erhalten. Das ZonedDateTime
wird konsequent einen über den anderen ziehen … aber das ist nicht immer die richtige Wahl.
Nun, dies könnte ein Problem für alle Anwendungen sein, die konstruieren ZonedDateTime
Werte so. Aber aus der Perspektive von jemandem, der eine Unternehmensanwendung erstellt, ist es ein größeres Problem, wenn die (möglicherweise falsche) ZonedDateTime
Werte sind persistent und werden später verwendet.
Die akzeptierte Antwort gibt eine sehr vollständige Erklärung, vielleicht kann Ihnen das folgende Codebeispiel ein kurzes und klares Bild vermitteln:
Instant instant = Instant.now();
Clock clock = Clock.fixed(instant, ZoneId.of("America/New_York"));
OffsetDateTime offsetDateTime = OffsetDateTime.now(clock);
ZonedDateTime zonedDateTime = ZonedDateTime.now(clock);
System.out.println(offsetDateTime); // 2019-01-03T19:10:16.806-05:00
System.out.println(zonedDateTime); // 2019-01-03T19:10:16.806-05:00[America/New_York]
System.out.println();
OffsetDateTime offsetPlusSixMonths = offsetDateTime.plusMonths(6);
ZonedDateTime zonedDateTimePlusSixMonths = zonedDateTime.plusMonths(6);
System.out.println(offsetPlusSixMonths); // 2019-07-03T19:10:16.806-05:00
System.out.println(zonedDateTimePlusSixMonths); // 2019-07-03T19:10:16.806-04:00[America/New_York]
System.out.println(zonedDateTimePlusSixMonths.toEpochSecond() - offsetPlusSixMonths.toEpochSecond()); // -3600
System.out.println();
System.out.println(zonedDateTimePlusSixMonths.toLocalDateTime()); // 2019-07-03T19:10:16.806
System.out.println(offsetPlusSixMonths.toLocalDateTime()); // 2019-07-03T19:10:16.806
Kurz gesagt, verwenden ZonedDateTime
Nur wenn Sie die Sommerzeit berücksichtigen möchten, gibt es normalerweise eine Stunde Unterschied, wie Sie im obigen Beispiel sehen können, die Verschiebung ZonedDateTime
Wechsel von -5:00
zu -04:00
in den meisten Fällen kann Ihre Geschäftslogik mit einem Fehler enden.
(Codekopie von https://www.youtube.com/watch?v=nEQhx9hGutQ)
Grundsätzlich a
ZonedDateTime
enthält auch Informationen über Zeitzonen, einschließlich DST-Umschaltung usw. von dem, was ich gelesen habe.– fg
14. Mai 2015 um 10:21 Uhr