Jaka jest różnica między ZonedDateTime i OffsetDateTime?

155

Przeczytałem dokumentację, ale nadal nie mogę uzyskać, kiedy powinienem użyć jednej lub drugiej:

Zgodnie z dokumentacją OffsetDateTimenależy używać przy zapisywaniu daty do bazy, ale nie rozumiem dlaczego.

Zhenya
źródło
4
Zasadniczo a ZonedDateTimezawiera również informacje o strefach czasowych, w tym przełączaniu na czas letni itp. Z tego, co przeczytałem.
fge

Odpowiedzi:

187

P: Jaka jest różnica między java 8 ZonedDateTime i OffsetDateTime?

Tak mówią javadoc:

" OffsetDateTime, ZonedDateTimeA Instantcały zapas instant na linii czasu do precyzji nanosekund. InstantJest to najprostszy, wystarczy reprezentujący chwili. OffsetDateTimeDodaje do chwili przesunięcie od UTC / Greenwich, który pozwala lokalnym data-czas, aby być uzyskane. ZonedDateTimeDodaje pełny etat Zasady strefy. "

Źródło: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html

Zatem różnica między OffsetDateTimei ZonedDateTimepolega na tym, że ta ostatnia obejmuje zasady, które obejmują korekty czasu letniego i różne inne anomalie.

Mówiąc prosto:

Strefa czasowa = ( przesunięcie-od-UTC + reguły-dla-anomalii)


P: Zgodnie z dokumentacją OffsetDateTimenależy używać przy zapisywaniu daty do bazy danych, ale nie rozumiem dlaczego.

Daty z lokalnymi przesunięciami czasowymi zawsze reprezentują te same momenty w czasie i dlatego mają stabilną kolejność. Z kolei znaczenie dat z pełnymi informacjami o strefie czasowej jest niestabilne w obliczu dostosowań zasad dla odpowiednich stref czasowych. (I to się zdarza; np. Dla wartości daty i czasu w przyszłości). Jeśli więc zapiszesz, a następnie odzyskasz ZonedDateTimeimplementację, wystąpi problem:

  • Może przechowywać obliczone przesunięcie ... a następnie pobrany obiekt może mieć przesunięcie, które jest niezgodne z bieżącymi regułami dla identyfikatora strefy.

  • Może odrzucić obliczone przesunięcie ... a pobrany obiekt reprezentuje inny punkt na absolutnej / uniwersalnej osi czasu niż ten, który został zapisany.

Jeśli używasz serializacji obiektów Java, implementacja Java 9 przyjmuje pierwsze podejście. Jest to prawdopodobnie „bardziej poprawny” sposób radzenia sobie z tym problemem, ale nie wydaje się, aby to zostało udokumentowane. (Sterowniki JDBC i wiązania ORM przypuszczalnie podejmują podobne decyzje i miejmy nadzieję, że robią to dobrze).

Ale jeśli piszesz aplikację, która ręcznie przechowuje wartości daty / czasu lub która polega na tym java.sql.DateTime, radzenie sobie z komplikacjami związanymi z identyfikatorem strefy jest ... prawdopodobnie czymś, czego należy unikać. Stąd rada.

Zwróć uwagę, że daty, których znaczenie / kolejność są niestabilne w czasie, mogą być problematyczne dla aplikacji. A ponieważ zmiany w regułach stref to przypadek skrajny, problemy mogą pojawić się w nieoczekiwanych momentach.


Drugim (możliwym) powodem porady jest to, że konstrukcja a ZonedDateTimejest niejednoznaczna w pewnych punktach. Na przykład w okresie, w którym „cofasz zegary”, połączenie czasu lokalnego i identyfikatora strefy może dać dwa różne przesunięcia. ZonedDateTimeBędzie konsekwentnie wybrać jeden nad drugim ... ale nie zawsze jest to właściwy wybór.

Może to stanowić problem dla wszystkich aplikacji, które konstruują ZonedDateTimewartości w ten sposób. Ale z perspektywy kogoś, kto buduje aplikację korporacyjną, większy problem jest, gdy (prawdopodobnie niepoprawne) ZonedDateTimewartości są trwałe i używane później.

Stephen C.
źródło