sql >> Base de Datos >  >> RDS >> Mysql

Zonas horarias de Java Date y 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).
) ;

Evite las clases de fecha y hora heredadas

Está utilizando terribles clases de fecha y hora que fueron suplantadas hace años por java.time clases

Nunca use Date o Timestamp .

UTC

Captura el momento actual, en UTC. La mayoría de las bases de datos almacenan un momento en UTC. Y, en general, debe realizar la mayor parte de su lógica comercial, depuración, registro, almacenamiento e intercambio de datos en UTC.

OffsetDateTime

Representar un momento con un desplazamiento desde UTC usando el bien llamado OffsetDateTime clase.

Queremos UTC en sí, o una compensación de cero. Podemos usar una constante para eso, ZoneOffset.UTC .

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

JDBC 4.2

A partir de JDBC 4.2 podemos intercambiar directamente java.time objetos con la base de datos.

Para guardar este momento en una columna de un tipo de datos similar al estándar SQL TIMESTAMP WITH TIME ZONE :

myPreparedStatement.setObject( … , odt ) ;

Recuperación:

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

ZonedDateTime

Para presentar este momento recuperado al usuario, es posible que desee ajustarse a la zona horaria esperada/deseada del usuario.

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

Nunca confíes en la zona horaria predeterminada

Observe en el código anterior que siempre especificamos la zona o el desplazamiento deseado/esperado.

Si no lo especifica, se aplica implícitamente un desfase o una zona. Es mejor especificar sus intenciones explícitamente ya que el valor predeterminado actual de su JVM, base de datos y sistema operativo host están fuera de sus manos como programador. Lo que significa que el código que se basa en el valor predeterminado variará en comportamiento en tiempo de ejecución.

Java 6 y 7

El mismo hombre, Stephen Colebourne, que dirige JSR 310 y java.time implementación, así como el famoso Joda-Time proyecto, también lidera otro proyecto, ThreeTen-Backport . La mayor parte del java.time la funcionalidad está adaptada a Java 6 y 7 en esta biblioteca, con una API casi idéntica.

Así que haga todo su trabajo en clases de back-port. Luego, en el último momento, convierta a/desde java.sql.Timestamp a través de DateTimeUtils clase.

Esos métodos de conversión utilizan principalmente Instant objetos. Un Instant es un momento en UTC, siempre en UTC. Puede ajustar desde su OffsetDateTime a UTC extrayendo un Instant . El Instant class es la clase de bloque de construcción básica en java.time , con OffsetDateDate tener más flexibilidad, como patrones de formato alternativos al generar una cadena. Pero tanto Instant y OffsetDateTime representan un momento, un punto en la línea de tiempo.

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

Yendo en la otra dirección, recuperando una Timestamp desde su base de datos, luego se convierte inmediatamente a un Instant .

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

Acerca de java.time

El java.time framework está integrado en Java 8 y versiones posteriores. Estas clases reemplazan al viejo y problemático legacy clases de fecha y hora como java.util.Date , Calendar , &SimpleDateFormat .

El Joda-Time proyecto, ahora en modo de mantenimiento , recomienda la migración a java.time clases.

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

Puede intercambiar java.time objetos directamente con su base de datos. Use un controlador JDBC compatible con JDBC 4.2 o después. Sin necesidad de cadenas, sin necesidad de java.sql.* clases.

¿Dónde obtener las clases java.time?

El ThreeTen-Extra proyecto extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval , YearWeek , YearQuarter y más .