Mysql
 sql >> Database >  >> RDS >> Mysql

Java Date e MySQL timestamp fusi orari

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).
) ;

Evita le classi data-ora precedenti

Stai usando classi di data e ora terribili che sono state soppiantate anni fa da java.time classi.

Non utilizzare mai Date o Timestamp .

UTC

Cattura il momento attuale, in UTC. La maggior parte dei database memorizza un momento in UTC. E generalmente dovresti eseguire la maggior parte della tua logica aziendale, debugging, registrazione, archiviazione e scambio di dati in UTC.

OffsetDateTime

Rappresenta un momento con un offset da UTC usando il nome appropriato OffsetDateTime classe.

Vogliamo lo stesso UTC o un offset di zero. Possiamo usare una costante per questo, ZoneOffset.UTC .

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

JDBC 4.2

A partire da JDBC 4.2 possiamo scambiare direttamente java.time oggetti con il database.

Per salvare questo momento in una colonna di un tipo di dati simile allo standard SQL TIMESTAMP WITH TIME ZONE :

myPreparedStatement.setObject( … , odt ) ;

Recupero:

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

ZonedDateTime

Per presentare all'utente questo momento recuperato, potresti voler adattare il fuso orario previsto/desiderato dell'utente.

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

Non fare mai affidamento sul fuso orario predefinito

Nota nel codice sopra che abbiamo sempre specificato l'offset o la zona desiderati/previsti.

Se non si specifica, viene applicato un offset o una zona in modo invisibile all'utente. È meglio specificare le tue intenzioni in modo esplicito poiché l'attuale impostazione predefinita della tua JVM, database e sistema operativo host è fuori dalle tue mani come programmatore. Ciò significa che il codice che si basa sull'impostazione predefinita varierà nel comportamento in fase di esecuzione.

Java 6 e 7

Lo stesso uomo, Stephen Colebourne, che guida JSR 310 e java.time implementazione, così come il famoso Joda-Time progetto, guida anche un altro progetto, ThreeTen-Backport . La maggior parte del java.time la funzionalità è stata trasferita su Java 6 e 7 in questa libreria, con API quasi identiche.

Quindi fai tutto il tuo lavoro nelle classi back-port. Quindi, all'ultimo momento, converti in/da java.sql.Timestamp tramite DateTimeUtils classe.

Questi metodi di conversione utilizzano principalmente Instant oggetti. Un Instant è un momento in UTC, sempre in UTC. Puoi regolare dal tuo OffsetDateTime in UTC estraendo un Instant . Il Instant class è la classe di base in java.time , con OffsetDateDate avere una maggiore flessibilità come modelli di formattazione alternativi durante la generazione di una stringa. Ma entrambi Instant e OffsetDateTime rappresentano un momento, un punto sulla timeline.

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

Andando nell'altra direzione, recuperando un Timestamp dal tuo database, quindi convertendolo immediatamente in un Instant .

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

Informazioni su java.time

Il java.time framework è integrato in Java 8 e versioni successive. Queste classi soppiantano la vecchia e problematica eredità classi data-ora come java.util.Date , Calendar , &SimpleDateFormat .

Il Joda-Time progetto, ora in modalità di manutenzione , consiglia la migrazione a java.time classi.

Per ulteriori informazioni, consulta il Tutorial Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .

Puoi scambiare java.time oggetti direttamente con il tuo database. Utilizzare un driver JDBC conforme a JDBC 4.2 o più tardi. Non c'è bisogno di stringhe, non c'è bisogno di java.sql.* classi.

Dove ottenere le classi java.time?

Il ThreeTen-Extra il progetto estende java.time con classi aggiuntive. Questo progetto è un banco di prova per possibili future aggiunte a java.time. Potresti trovare alcune classi utili qui come Interval , YearWeek , YearQuarter e altro .