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

Fuseaux horaires Java Date et MySQL timestamp

tl;dr

myPreparedStatement
.setObject(  
    … ,                                   // Specify which placeholder `?` in your SQL statement. 
    OffsetDateTime.now( ZoneOffset.UTC )  // Capture the current moment as seen in the wall-clock time of UTC (an offset-from-UTC of zero).
) ;

Évitez les anciennes classes de date et d'heure

Vous utilisez de terribles classes date-heure qui ont été supplantées il y a des années par le java.time Des classes.

Ne jamais utiliser Date ou Timestamp .

UTC

Capturez le moment actuel, en UTC. La plupart des bases de données stockent un moment en UTC. Et généralement, vous devriez faire la plupart de votre logique métier, du débogage, de la journalisation, du stockage et de l'échange de données en UTC.

OffsetDateTime

Représentez un moment avec un décalage par rapport à UTC en utilisant le bien nommé OffsetDateTime classer.

Nous voulons UTC lui-même, ou un décalage de zéro. Nous pouvons utiliser une constante pour cela, ZoneOffset.UTC .

OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ) ;

JDBC 4.2

Depuis JDBC 4.2, nous pouvons échanger directement java.time objets avec la base de données.

Pour enregistrer ce moment dans une colonne d'un type de données semblable au standard SQL TIMESTAMP WITH TIME ZONE :

myPreparedStatement.setObject( … , odt ) ;

Récupération :

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

ZonedDateTime

Pour présenter ce moment récupéré à l'utilisateur, vous souhaiterez peut-être vous adapter au fuseau horaire attendu/souhaité de l'utilisateur.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

Ne vous fiez jamais au fuseau horaire par défaut

Notez dans le code ci-dessus que nous avons toujours spécifié le décalage ou la zone souhaité/attendu.

Si vous ne le spécifiez pas, un décalage ou une zone est implicitement appliqué de manière silencieuse. Mieux vaut spécifier explicitement vos intentions car les valeurs par défaut actuelles de votre JVM, de votre base de données et de votre système d'exploitation hôte ne sont pas entre vos mains en tant que programmeur. Ce qui signifie que le code reposant sur la valeur par défaut aura un comportement différent lors de l'exécution.

Java 6 et 7

Le même homme, Stephen Colebourne, qui dirige JSR 310 et le java.time implémentation, ainsi que le fameux Joda-Time projet, dirige également un autre projet, ThreeTen-Backport . La plupart du temps java.time la fonctionnalité est rétroportée vers Java 6 et 7 dans cette bibliothèque, avec une API presque identique.

Alors faites tout votre travail dans des classes de back-port. Puis, au dernier moment, convertissez vers/depuis java.sql.Timestamp via DateTimeUtils classer.

Ces méthodes de conversion utilisent principalement Instant objets. Un Instant est un moment en UTC, toujours en UTC. Vous pouvez ajuster à partir de votre OffsetDateTime vers UTC en extrayant un Instant . L'Instant class est la classe de base du bloc de construction dans java.time , avec OffsetDateDate avoir plus de flexibilité, comme des modèles de formatage alternatifs lors de la génération d'une chaîne. Mais à la fois Instant et OffsetDateTime représenter un moment, un point sur la chronologie.

Instant instant = odt.toInstant() ;  
java.sql.Timestamp ts = org.threeten.bp.DateTimeUtils.toSqlTimestamp( instant ) ;

Dans l'autre sens, récupérer un Timestamp de votre base de données, puis conversion immédiate en Instant .

java.sql.Timestamp ts = myResultSet.getTimestamp( … ) ;
Instant instant = org.threeten.bp.DateTimeUtils.toInstant( ts ) ;

À 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 .

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

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

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 .