Quelle est la différence entre ZonedDateTime et OffsetDateTime?

155

J'ai lu la documentation, mais je n'arrive toujours pas à savoir quand je devrais utiliser l'un ou l'autre:

Selon la documentation OffsetDateTimedoit être utilisé lors de l'écriture de la date dans la base de données, mais je ne comprends pas pourquoi.

Zhenya
la source
4
Fondamentalement, un ZonedDateTimecontient également des informations sur les fuseaux horaires, y compris la commutation DST, etc. d'après ce que j'ai lu.
fge

Réponses:

187

Q: Quelle est la différence entre java 8 ZonedDateTime et OffsetDateTime?

Les javadocs disent ceci:

" OffsetDateTime, ZonedDateTimeet Instanttous stockent un instant sur la ligne de temps avec une précision nanoseconde. Instantest le plus simple, représentant simplement l'instant. OffsetDateTimeajoute à l'instant le décalage par rapport à UTC / Greenwich, ce qui permet d'obtenir la date-heure locale. ZonedDateTimeajoute le temps plein -règles de zone. "

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

Ainsi la différence entre OffsetDateTimeetZonedDateTime est que ce dernier comprend les règles qui couvrent les ajustements de l'heure d'été et diverses autres anomalies.

Dit simplement:

Fuseau horaire = ( Offset-From-UTC + Rules-For-Anomalies)


Q: Selon la documentation OffsetDateTimedoit être utilisé lors de l'écriture de la date dans la base de données, mais je ne comprends pas pourquoi.

Les dates avec décalages horaires locaux représentent toujours les mêmes instants dans le temps, et ont donc un ordre stable. En revanche, la signification des dates avec des informations de fuseau horaire complètes est instable face aux ajustements des règles pour les fuseaux horaires respectifs. (Et cela se produit; par exemple, pour les valeurs date-heure dans le futur.) Donc, si vous stockez puis récupérez un, ZonedDateTimel'implémentation a un problème:

  • Il peut stocker l'offset calculé ... et l'objet récupéré peut alors avoir un offset qui est incompatible avec les règles actuelles pour l'ID de zone.

  • Il peut ignorer le décalage calculé ... et l'objet récupéré représente alors un point différent dans la chronologie absolue / universelle de celui qui a été stocké.

Si vous utilisez la sérialisation d'objets Java, l'implémentation Java 9 adopte la première approche. C'est sans doute la manière «la plus correcte» de gérer cela, mais cela ne semble pas être documenté. (Les pilotes JDBC et les liaisons ORM prennent vraisemblablement des décisions similaires et, espérons-le, font les choses correctement.)

Mais si vous écrivez une application qui stocke manuellement les valeurs de date / heure, ou qui reposent sur java.sql.DateTime, alors traiter les complications d'un identifiant de zone est ... probablement quelque chose à éviter. D'où le conseil.

Notez que les dates dont la signification / l'ordre est instable dans le temps peuvent être problématiques pour une application. Et comme les modifications des règles de zone sont un cas extrême, les problèmes sont susceptibles d'apparaître à des moments inattendus.


Une deuxième raison (possible) pour le conseil est que la construction de a ZonedDateTimeest ambiguë sur certains points. Par exemple, dans la période où vous "remettez les horloges en arrière", la combinaison d'une heure locale et d'un identifiant de zone peut vous donner deux décalages différents. Ils ZonedDateTimechoisiront systématiquement l'un sur l'autre ... mais ce n'est pas toujours le bon choix.

Maintenant, cela pourrait être un problème pour toutes les applications qui construisent des ZonedDateTimevaleurs de cette façon. Mais du point de vue de quelqu'un qui crée une application d'entreprise, c'est un problème plus important lorsque les ZonedDateTimevaleurs (éventuellement incorrectes) sont persistantes et utilisées plus tard.

Stephen C
la source