Was ist der Unterschied zwischen ZonedDateTime und OffsetDateTime?

Lesezeit: 4 Minuten

Benutzer-Avatar
Zhenya

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.

  • 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

Benutzer-Avatar
Stefan C

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:00in den meisten Fällen kann Ihre Geschäftslogik mit einem Fehler enden.

(Codekopie von https://www.youtube.com/watch?v=nEQhx9hGutQ)

  • Ich würde den umgekehrten Weg gehen: Die richtige zu verwenden ist normalerweise entweder Instant oder ZonedDateTime. Meiner Meinung nach OffsetDateTime existieren nur, weil viele existierende Systeme (fälschlicherweise) “Zeitverschiebung” als ausreichende Information über Zeitzonen behandeln (dh sie kommunizieren/speichern/handhaben nur eine Verschiebung, wenn sie einen Zeitzonennamen übermitteln sollten).

    – Joachim Sauer

    25. Mai 2021 um 7:50 Uhr


  • @JoachimSauer Wenn wir Nachrichten für Benutzer formatieren oder ihre Eingaben lesen, verwenden wir ZonedDateTime & ZoneId. Wenn wir ein Zeitereignis in DB speichern, konvertieren wir es in UTC, OffsetDateTime ist im Grunde ein Zeitpunkt. UTC-Daten sind leicht vergleichbar (Vermeidung von TZ-Info-Lookups).

    – Givenkoa

    5. August 2021 um 10:45 Uhr

1351520cookie-checkWas ist der Unterschied zwischen ZonedDateTime und OffsetDateTime?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy