Dopo aver cercato e letto come gestire data e ora da/per Java e MySQL, sono ancora confuso.Ancora confuso da Java Timestamps ecc. Con MySQL
Diciamo che creo un oggetto java.util.Date
. Questo oggetto contiene il tempo in UTC. Qualsiasi formattazione o analisi in altri fusi orari può essere effettuata con ad es. java.text.SimpleDateFormat
.
Ora voglio memorizzare il mio oggetto data nel database MySQL in UTC. Ma quando uso il metodo setTimestamp()
in java.sql.PreparedStatement
mi sento un po 'confuso. Segue un esempio di codice in cui collaudo sia MySQL DATETIME che TIMESTAMP nella mia tabella. Inserisco anche le date con entrambi i metodi setString()
e 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();
Quando corro quanto sopra, ottengo il seguente output che è come previsto.
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]
Ma quando ho ispezionare la tabella nel database utilizzando lo strumento a riga di comando MySQL ottengo:
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 prima colonna è solo un tipo di testo in cui devo conservare l'UTC data formattata.
Nella prima riga, ho memorizzato le date utilizzando il metodo setString()
.
Nella seconda riga ho memorizzato la data utilizzando il metodo setTimestamp(i,t)
. Immagino che JDBC converta automaticamente la data usando il fuso orario predefinito (che ho impostato su EST) prima di memorizzarlo. Ma TIMESTAMP non dovrebbe essere sempre automaticamente archiviato in UTC. La documentazione di MySQL dice MySQL converte i valori TIMESTAMP dal fuso orario corrente a UTC per l'archiviazione e viceversa da UTC al fuso orario corrente per il recupero. (numero 1).
Infine, per la terza riga ho utilizzato lo pst.setTimestamp(2, t, utc.getCalendar());
per memorizzare la data con la speranza che il driver debba utilizzare il fuso orario UTC. Ma apparentemente no (numero 2).
Posso facilmente risolvere il problema per memorizzare le date in UTC impostando il fuso orario predefinito su UTC. Ma ancora, mi piacerebbe capire cosa sta succedendo per le due questioni di cui sopra.
* "ritorno da UTC al fuso orario corrente per il recupero" * è ciò che si vede lì nell'output. –
Grazie, ma potresti approfondire questo? – Peter
I timestamp sono memorizzati internamente in UTC, ma quando li si stampa usando il client 'mysql', vengono presentati nell'ora locale, come la documentazione di MySQL dice. Lo stesso per il numero 2. Qual è il problema qui? –