2010-11-08 10 views
25

Antes de escribir un Java Date en una columna SQL TIMESTAMP, ¿JDBC traduce la fecha de la zona horaria de la máquina virtual Java a la de la sesión de la base de datos?Antes de escribir una fecha de Java en una columna SQL TIMESTAMP, ¿JDBC traduce la fecha de la zona horaria de la JVM a la zona horaria de la sesión de la base de datos?

Por ejemplo, supongamos que la zona horaria de la máquina virtual Java es UTC y la zona horaria de la sesión de la base de datos es UTC-5. Si un programa Java intenta almacenar 2000-01-01 00:00:00 pasándolo a PreparedStatement#setTimestamp(int, Timestamp), de acuerdo con el estándar JDBC, ¿almacenará la base de datos TIMESTAMP '2000-01-01 00:00:00' o TIMESTAMP '1999-12-31 19:00:00'?

+2

Las zonas horarias son (o deberían ser) solo relevantes para la presentación de fechas, no para el almacenamiento. Entonces no debe haber traducción. Sin embargo, esto es una suposición, no una respuesta. – RedGrittyBrick

+0

Entonces RedGrittyBrick, ¿espera que la base de datos almacene 'TIMESTAMP '2000-01-01 00: 00: 00''? –

+0

RedGrittyBrick, la zona horaria es relevante para las fechas si almacena la zona horaria. Sin embargo, una columna SQL TIMESTAMP no almacena la zona horaria, por lo que tiene sentido almacenar fechas independientes de la ubicación (es decir, relativas a la zona horaria UTC). –

Respuesta

13

No, JDBC es solo una API sobre cómo el cliente puede acceder a la base de datos. Para el almacenamiento de marca de tiempo, esto tendrá que ser dependiente de la organización que escribe sus controladores de base de datos que cumplen con el estándar API de JDBC.

Here's una implementación de la implementación de MySQL de PreparedStatement. Parecen tomar la zona horaria JVM de Java a la zona horaria de MySQL (consulte el método setTimestampInternal()).

+1

Sí, tiene razón. De la implementación del controlador JDBC de MySQL está bastante claro que 'setTimestampInternal()' traduce la fecha dada a la zona horaria del servidor ('x = TimeUtil.changeTimezone (this.connection, x, tz, 2059 this.connection.getServerTimezone()); '). También formatea la fecha en una cadena usando 'SimpleDateFormat', que depende de la configuración regional. –

+3

Por el contrario, la implementación del controlador PostScriptQL JDBC de 'setTimestamp()' traduce la fecha dada usando la zona horaria JVM. Consulte los métodos 'AbstractJdbc2Statement # setTimestamp (int, Timestamp, Calendar)' en http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/jdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java?rev=1.118 & content-type = text/x-cvsweb-markup y 'TimestampUtils # toString (Calendar, Timestamp)' en http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/jdbc/pgjdbc/org/postgresql/jdbc2 /TimestampUtils.java?rev=1.23&content-type=text/x-cvsweb-markup. El manejo de la zona horaria depende del controlador JDBC. –

+0

@Derek Mahar, eso es lo que dije. La implementación de la API varía según la organización que escribe el controlador JDBC. No debe tomarse como un absoluto que si MySQL (ejemplo) convierte las zonas horarias antes de almacenar, SQLite (ejemplo) lo haría (lo cual no ocurre en absoluto). –

7

Ahora mi requisito es que debe almacenar el valor en GMT/UTC independientemente de la zona horaria de la JVM. ¿Hay alguna manera de configurar la zona horaria sobre la marcha y luego desarmarla una vez que haya terminado con JDBC?

Edit: Bien, encontré una manera de evitar ese problema. Lo hicieron los siguientes

TimeZone default = TimeZone.getDefault(); 
try 
{ 
    TimeZone.setDefault(TimeZone.getTimeZone("UTC")); 

    //Do stuff with JDBC 
} 
finally 
{ 
    TimeZone.setDefault(default); 
} 
+2

Esto podría generar una condición de carrera en caso de que otros subprocesos realicen cálculos al mismo tiempo en las fechas, suponiendo que la zona horaria predeterminada no es UTC. – m3th0dman

+4

** GUARDAR ** [Cambiar el valor predeterminado] (http://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html#setDefault-java.util.TimeZone-) zona horaria es negocio riesgoso. Este cambio * afecta a todos los códigos en todos los hilos * que se ejecutan en esta JVM, no solo al código local en su método. –

1

usted puede utilizar sobrecargados setTimestamp setter aceptar Calendar ejemplo, para especificar la zona horaria

muestra (Si está utilizando Joda de fecha y hora):

org.joda.time.DateTime sendDateUTC = new DateTime(DateTimeZone.UTC).withMillis(millis); 
statement.setTimestamp (1, sendDateUTC, sendDateUTC.toGregorianCalendar()); 

Según Javadoc: Conjuntos el parámetro designado para el valor dado java.sql.Timestamp, utilizando el objeto Calendar dado. El controlador utiliza el objeto Calendar para construir un valor SQL TIMESTAMP, que luego el controlador envía a la base de datos. Con un objeto Calendar, el controlador puede calcular la marca de tiempo teniendo en cuenta una zona horaria personalizada. Si no se especifica ningún objeto de calendario, el controlador utiliza la zona horaria predeterminada, que es la de la máquina virtual que ejecuta la aplicación.

void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal) 
    throws SQLException; 
-1

La especificación es ridícula. Java.util.Date almacena milisegundos de época en el marco de referencia GMT. Java.sql.Timestamp es una fecha más nanosegundos en el mismo marco de referencia. Todos los get y depreciadores no en desuso utilizan el marco de referencia GMT. Para cualquier tipo de cordura, la zona horaria predeterminada para almacenar una marca de tiempo debe ser GMT.

En una aplicación de varios niveles, el servidor de aplicaciones para el usuario, el controlador y el servidor de la base de datos podrían estar en distintas zonas horarias. Algunos de los niveles pueden estar en diferentes zonas horarias al mismo tiempo; por ejemplo, si está equilibrando la carga de Internet en un continente, o si tiene una aplicación móvil que se conecta a un servidor central. Un entorno operativo en la nube sería prácticamente el mismo escenario en el que no tienes idea de dónde se ejecutará el controlador JDBC, ni ninguna garantía que nunca cambie.

La única forma que conozco de lograr consistencia en estos entornos es usar solo el parámetro setter y ResultSet getter que aceptan un calendario, y asegurarse de que cada aplicación que accede a los datos use algún calendario, preferiblemente GMT o UTC.

+0

Chris, no estoy seguro de que hayas respondido la pregunta de Derek. ¿Jdbc jdbc ajustará la marca de tiempo según la diferencia de zona horaria entre el cliente y el servidor? Estoy bastante seguro de que la respuesta es no. – Andreas

Cuestiones relacionadas