After searching and reading about how to handle date and time to / from Java and MySQL, I am still confused.
Suppose I create a java.util.Date object. This object stores time in UTC. Any formatting or parsing in other time zones can be performed, for example. java.text.SimpleDateFormat .
Now I want to save my date object in a MySQL database in UTC. But when I use the setTimestamp() method in setTimestamp() , I'm a little confused. Below is an example code example in which I test MySQL DATETIME and TIMESTAMP in my table. I also insert dates using the setString() and setTimestamp() methods.
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();
When I run above, I get the following result, which is as expected.
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]
But when I check the table in the database using the MySQL command line tool, I get:
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)
The first column is just a TEXT type, where I store the date in UTC.
On the first line, I saved the dates using the setString() method.
In the second line, I saved the date using the setTimestamp(i,t) method. I assume JDBC will automatically convert the date using the default time zone (which I set to EST) before it saves it. But you should not always save TIMESTAMP in UTC. The MySQL documentation says that MySQL converts TIMESTAMP values from the current time zone to UTC for storage and back from UTC to the current time zone for retrieval. (Issue 1).
Finally, for the third line, I used pst.setTimestamp(2, t, utc.getCalendar()); to store the date with the hope that the driver should use the UTC time zone. But apparently not (problem 2).
I can easily fix the problem of storing dates in UTC by setting the default time zone in UTC. Nevertheless, I would like to understand what is happening on the two above issues.