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

JPA Enregistrement d'une date erronée dans la base de données MySQL

tl;dr

Utilisez JPA 2.2 pour son support de java.time .

Utilisez une classe de date uniquement en Java pour travailler avec des valeurs de date uniquement en SQL.

LocalDate                           // Represent a date-only, without a time-of-day and without a time zone.
.now(                               // Get today's date…
    ZoneId.of( "Africa/Tunis" )     // …as seen in the wall-clock time used by the people of a particular region.
)                                   // Returns a `LocalDate` object.
.plusMonths( 1 )                    // Returns another `LocalDate` object, per immutable objects pattern.

java.time

JPA 2.2 prend désormais en charge le java.time moderne Des classes. Plus besoin d'utiliser Joda-Time.

Ne pas utilisez java.sql.Date . Cette classe fait semblant pour représenter une date uniquement mais a en fait une heure du jour définie sur UTC en raison de la terrible décision de conception d'hériter de java.util.Date (qui malgré son nom représente une date et une heure de la journée et un décalage de zéro pour UTC lui-même). Ces classes héritées sont un horrible gâchis misérable. Sun, Oracle et la communauté JCP ont tous abandonné ces cours il y a des années avec l'adoption de JSR 310, et vous devriez en faire autant.

LocalDate

La LocalDate la classe représente une valeur de date uniquement sans heure du jour et sans fuseau horaire ou offset-from-UTC .

Un fuseau horaire est crucial pour déterminer une date. Pour un moment donné, la date varie autour du globe par zone. Par exemple, quelques minutes après minuit à Paris France est un nouveau jour tout en restant "hier" à Montréal Québec .

Si aucun fuseau horaire n'est spécifié, la JVM applique implicitement son fuseau horaire par défaut actuel. Cette valeur par défaut peut modifier à tout moment pendant l'exécution (!), vos résultats peuvent donc varier. Mieux vaut spécifier explicitement votre fuseau horaire souhaité/attendu comme argument. Si critique, confirmez la zone avec votre utilisateur.

Spécifiez un nom de fuseau horaire approprié au format Continent/Region , comme America/Montreal , Africa/Casablanca , ou Pacific/Auckland . N'utilisez jamais l'abréviation de 2 à 4 lettres telle que EST ou IST comme ils ne le sont pas de vrais fuseaux horaires, non normalisés, et même pas uniques (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Si vous souhaitez utiliser le fuseau horaire par défaut actuel de la JVM, demandez-le et transmettez-le comme argument. S'il est omis, le code devient ambigu à lire dans la mesure où nous ne savons pas avec certitude si vous aviez l'intention d'utiliser la valeur par défaut ou si vous, comme tant de programmeurs, n'étiez pas au courant du problème.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Ou indiquez une date. Vous pouvez définir le mois par un nombre, avec une numérotation saine de 1 à 12 pour janvier à décembre.

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

Ou, mieux, utilisez le Month objets enum prédéfinis, un pour chaque mois de l'année. Astuce :Utilisez ces Month des objets dans votre base de code plutôt qu'un simple nombre entier pour rendre votre code plus auto-documenté, garantir des valeurs valides et fournir sécurité de type . Idem pour Year &YearMonth .

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

Mathématiques date-heure

Apparemment, vous voulez commencer avec une date et obtenir un mois plus tard comme plage de dates.

LocalDate monthLater = ld.plusMonths( 1 ) ;

JDBC 4.2

Depuis JDBC 4.2, votre pilote JDBC doit prendre en charge certaines des clés java.time des classes telles que LocalDate .

Plage de dates

Notez les liens ci-dessous pour ThreeTen-Extra . Vous pouvez trouver le LocalDateRange classe là pour être pratique si vous travaillez beaucoup avec des plages de dates.

À propos de java.time

Le java.time framework est intégré à Java 8 et versions ultérieures. Ces classes supplantent l'ancien héritage gênant les classes date-heure telles que java.util.Date , Calendar , &SimpleDateFormat .

Pour en savoir plus, consultez le tutoriel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Le Joda-Time projet, maintenant en mode maintenance , conseille la migration vers java.time cours.

Vous pouvez échanger java.time objets directement avec votre base de données. Utilisez un pilote JDBC conforme à JDBC 4.2 ou plus tard. Pas besoin de chaînes, pas besoin de java.sql.* cours.

Où obtenir les classes java.time ?

Le ThreeTen-Extra Le projet étend java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels futurs ajouts à java.time. Vous pouvez trouver ici des classes utiles telles que Interval , YearWeek , YearQuarter , et plus .