Después de buscar y leer acerca de cómo manejar la fecha y la hora desde/hacia Java y MySQL, todavía estoy confundido.Aún confundido por Java Timestamps, etc. con MySQL
Digamos que creo un objeto java.util.Date
. Ese objeto tiene tiempo en UTC. Cualquier formateo o análisis en otras zonas horarias se puede hacer con, p. java.text.SimpleDateFormat
.
Ahora quiero almacenar mi objeto de fecha en la base de datos MySQL en UTC. Pero cuando uso el método setTimestamp()
en java.sql.PreparedStatement
me confundo un poco. Aquí sigue un ejemplo de código donde pruebo tanto MySQL DATETIME como TIMESTAMP en mi tabla. También inserto las fechas con los métodos setString()
y setTimestamp()
.
java.sql.Connection conn = java.sql.DriverManager.getConnection("jdbc:mysql://localhost/test","user","password");
java.sql.Statement st = conn.createStatement();
String q = "DROP TABLE IF EXISTS tmp";
st.execute(q);
q = "CREATE TABLE tmp (dt_string TEXT, dt DATETIME, ts TIMESTAMP)";
st.execute(q);
java.sql.PreparedStatement pst = conn.prepareStatement("INSERT INTO tmp SET dt_string=?, dt=?, ts=?");
java.text.SimpleDateFormat utc = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
utc.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("EST"));
System.out.println("Default time zone: " + java.util.TimeZone.getDefault().getID());
java.util.Date d = new java.util.Date();
System.out.println("A date: " + d);
java.sql.Timestamp t = new java.sql.Timestamp(d.getTime());
System.out.println("The timestamp: " + t);
pst.setString(1, utc.format(d));
pst.setString(2, utc.format(d));
pst.setString(3, utc.format(t));
pst.execute();
pst.setTimestamp(2, t);
pst.setTimestamp(3, t);
pst.execute();
System.out.println("Use calendar: " + utc.getCalendar().getTimeZone());
pst.setTimestamp(2, t, utc.getCalendar());
pst.setTimestamp(3, t, utc.getCalendar());
pst.execute();
conn.close();
Cuando ejecuto lo anterior, obtengo la siguiente salida, que es la esperada.
Default time zone: EST
A date: Thu Mar 22 08:49:51 EST 2012
The timestamp: 2012-03-22 08:49:51.784
Use calendar: sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
Pero cuando examino la tabla en la base de datos utilizando la herramienta de línea de comandos de MySQL me sale:
mysql> select * from tmp;
+---------------------+---------------------+---------------------+
| dt_string | dt | ts |
+---------------------+---------------------+---------------------+
| 2012-03-22 13:49:51 | 2012-03-22 13:49:51 | 2012-03-22 13:49:51 |
| 2012-03-22 13:49:51 | 2012-03-22 08:49:51 | 2012-03-22 08:49:51 |
| 2012-03-22 13:49:51 | 2012-03-22 08:49:51 | 2012-03-22 08:49:51 |
+---------------------+---------------------+---------------------+
3 rows in set (0.00 sec)
La primera columna es sólo un tipo de texto donde almaceno la UTC fecha formateada.
En la primera fila, guardé las fechas usando el método setString()
.
En la segunda fila almacené la fecha usando el método setTimestamp(i,t)
. Supongo que JDBC convierte automáticamente la fecha usando la zona horaria predeterminada (que establecí en EST) antes de que la almacene. Pero TIMESTAMP no siempre debe almacenarse automáticamente en UTC. La documentación de MySQL dice MySQL convierte los valores de TIMESTAMP de la zona horaria actual a UTC para el almacenamiento y de regreso de UTC a la zona horaria actual para la recuperación. (Número 1).
Finalmente, para la tercera fila utilicé el pst.setTimestamp(2, t, utc.getCalendar());
para almacenar la fecha con la esperanza de que el controlador utilice la zona horaria UTC. Pero aparentemente no (Problema 2).
Puedo solucionar fácilmente el problema de almacenar fechas en UTC estableciendo la zona horaria predeterminada en UTC. Pero aún así, me gustaría entender qué está pasando en los dos temas anteriores.
* "de vuelta de UTC a la zona horaria actual para la recuperación" * es lo que ves allí en la salida. –
Gracias, pero ¿podría ampliar esto? – Peter
Las marcas de tiempo se almacenan en UTC internamente, pero cuando las muestra usando el cliente 'mysql', se le presentan en la hora local, como lo indica la documentación de MySQL. Lo mismo para el problema 2. ¿Cuál es el problema aquí? –