¿Cuál es la diferencia entre ZonedDateTime y OffsetDateTime?

155

He leído la documentación, pero todavía no puedo saber cuándo debo usar uno u otro:

De acuerdo con la documentación, se OffsetDateTimedebe usar al escribir la fecha en la base de datos, pero no entiendo por qué.

Zhenya
fuente
44
Básicamente, a ZonedDateTimetambién contiene información sobre zonas horarias, incluido el cambio de horario de verano, etc. de lo que leí.
fge

Respuestas:

187

P: ¿Cuál es la diferencia entre java 8 ZonedDateTime y OffsetDateTime?

Los javadocs dicen esto:

" OffsetDateTime, ZonedDateTimey Instanttodos almacenan un instante en la línea de tiempo con una precisión de nanosegundos. InstantEs el más simple, simplemente representa el instante. OffsetDateTimeAgrega al instante el desplazamiento de UTC / Greenwich, que permite obtener la fecha y hora local. ZonedDateTimeAgrega tiempo completo -reglas de zona ".

Fuente: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html

Por lo tanto, la diferencia entre OffsetDateTimey ZonedDateTimees que este último incluye las reglas que cubren los ajustes del horario de verano y otras anomalías.

Dicho simplemente:

Zona horaria = ( Offset-From-UTC + Rules-For-Anomalies)


P: Según la documentación, se OffsetDateTimedebe utilizar al escribir la fecha en la base de datos, pero no entiendo por qué.

Las fechas con desfases de hora local siempre representan los mismos instantes en el tiempo y, por lo tanto, tienen un orden estable. Por el contrario, el significado de las fechas con información de zona horaria completa es inestable ante los ajustes a las reglas para las zonas horarias respectivas. (Y esto sucede; por ejemplo, para valores de fecha y hora en el futuro). Entonces, si almacena y luego recupera un, ZonedDateTimela implementación tiene un problema:

  • Puede almacenar el desplazamiento calculado ... y el objeto recuperado puede tener un desplazamiento que sea inconsistente con las reglas actuales para el id de zona.

  • Puede descartar el desplazamiento calculado ... y el objeto recuperado representa un punto diferente en la línea de tiempo absoluta / universal que el que estaba almacenado.

Si utiliza la serialización de objetos Java, la implementación de Java 9 toma el primer enfoque. Esta es posiblemente la forma "más correcta" de manejar esto, pero esto no parece estar documentado. (Los controladores JDBC y los enlaces ORM presumiblemente están tomando decisiones similares, y con suerte lo están haciendo bien).

Pero si está escribiendo una aplicación que almacena manualmente los valores de fecha / hora, o en los que se basa java.sql.DateTime, entonces lidiar con las complicaciones de un id de zona es ... probablemente algo que debe evitarse. De ahí el consejo.

Tenga en cuenta que las fechas cuyo significado / orden es inestable en el tiempo pueden ser problemáticas para una aplicación. Y dado que los cambios en las reglas de zona son un caso marginal, los problemas pueden surgir en momentos inesperados.


Una (posible) segunda razón para el consejo es que la construcción de un ZonedDateTimees ambigua en ciertos puntos. Por ejemplo, en el período de tiempo en el que está "retrasando los relojes", combinar una hora local y un id de zona puede proporcionarle dos compensaciones diferentes. El ZonedDateTimeescogerá siempre uno sobre el otro ... pero esto no es siempre la elección correcta.

Ahora, esto podría ser un problema para cualquier aplicación que construya ZonedDateTime valores de esa manera. Pero desde la perspectiva de alguien que crea una aplicación empresarial es un problema mayor cuando los ZonedDateTimevalores (posiblemente incorrectos) son persistentes y se usan más tarde.

Stephen C
fuente