Mysql
 sql >> Base de données >  >> RDS >> Mysql

JPA TemporalType.Date donnant une date erronée

Très désolé mais toutes les réponses jusqu'à présent sont généralement incorrectes. La réponse est assez simple mais nécessite que nous distinguions cinq points :

  1. DATE =java.sql.Date, qui est un wrapper autour de java.util.Date qui est le nombre de millisecondes depuis l'Epoch dans le fuseau horaire UTC. Cela a donc l'année/mois/date/heures/minutes/secondes dans un fuseau horaire fixe GMT+0 (UTC). Notez cependant que java.sql.Date met les composants de temps à zéro !
  2. TIMESTAMP =java.sql.TimeStamp qui est un wrapper de composant autour de Date qui ajoute des fractions de secondes pour prendre en charge la norme de type SQL DATE. Cette classe/type n'est pas pertinente ou nécessaire pour cette question, mais en bref, elle contient la date et l'heure.
  3. La base de données stocke les objets DATE tels que définis (en utilisant UTC comme décalage depuis Java) mais peut traduire l'heure si elle est configurée dans la base de données pour être dans un fuseau horaire différent. Par défaut, la plupart des bases de données utilisent par défaut le fuseau horaire du serveur local, ce qui est une très mauvaise idée. Mesdames, messieurs... stockez TOUJOURS les objets DATE en UTC. Lisez la suite...
  4. L'heure dans la JVM et le fuseau horaire doivent être corrects. Étant donné que l'objet Date utilise UTC, un décalage est-il calculé pour l'heure de votre serveur ? Considérez cela avec la forte recommandation que l'heure du serveur soit définie sur GMT + 0 (UTC).
  5. Enfin, lorsque nous voulons rendre la DATE à partir de la base de données (en utilisant JSF ou autre), il devrait être configuré pour être le fuseau horaire GMT + 0 et, si cela est fait à partir du serveur vers le haut également ... vos dates et heures seront TOUJOURS cohérentes, référentielles et toutes les bonnes choses. Il ne reste plus qu'à afficher l'heure et c'est là que l'agent utilisateur (pour une application Web par exemple) pourrait être utilisé pour traduire l'heure GMT+0 dans le fuseau horaire "local" de l'utilisateur.

Résumé :Utilisez UTC (GMT+0) sur le serveur, dans la base de données, dans vos objets Java.

DATE et TIMESTAMP ne sont différents du point de vue de la base de données que dans la mesure où TIMESTAMP comporte des fractions de secondes supplémentaires. Les deux utilisent GMT+0 (sous-entendu). JodaTime est un cadre de calendrier préféré pour gérer tout cela, mais ne résoudra pas les problèmes de JVM incompatibles avec les paramètres de fuseau horaire de la base de données.

Si les conceptions d'applications de JVM à la base de données n'utilisent pas GMT, en raison de l'heure d'été, des ajustements d'horloge et de toutes sortes d'autres jeux régionaux qui se jouent dans les horloges locales mondiales ... les heures des transactions et tout le reste seront à jamais faussés , non référentiel, incohérent, etc.

Une autre bonne réponse connexe sur les types de données :java.util .Date contre java.sql.Date

Notez également que Java 8 a des mises à jour avec une meilleure gestion de la date/heure (enfin), mais cela ne résout pas le fait que l'horloge du serveur sur laquelle la JVM s'exécute soit dans un fuseau horaire et la base de données dans un autre. À ce stade, il y a toujours une traduction en cours. Dans chaque grand client (intelligent) avec lequel je travaille, les fuseaux horaires de la base de données et du serveur JVM sont définis sur UTC pour cette raison même si leurs opérations se produisent en grande partie dans un autre fuseau horaire.