После поиска и чтения о том, как обрабатывать дату и время в / из Java и MySQL, я все еще в замешательстве.
Допустим, я создаю java.util.Date
объект. Этот объект содержит время в UTC. Любое форматирование или разбор в другие часовые пояса может быть выполнено, например, с помощью java.text.SimpleDateFormat
.
Теперь я хочу сохранить свой объект date в базе данных MySQL в UTC. Но когда я использую метод setTimestamp()
в java.sql.PreparedStatement
, я немного растерялся. Ниже приведен пример кода, в котором я тестирую MySQL DATETIME и TIMESTAMP в своей таблице. Я также вставляю даты с помощью методов setString()
и 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();
Когда я запускаю вышеупомянутое, я получаю следующий вывод, который является ожидаемым.
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]
Но когда я проверяю таблицу в базе данных с помощью инструмента командной строки MySQL, я получаю:
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)
Первый столбец - это просто текстовый тип, в котором я храню дату в формате UTC.
В первой строке я сохранил даты, используя метод setString()
.
Во второй строке я сохранил дату, используя метод setTimestamp(i,t)
. Я предполагаю, что JDBC автоматически преобразует дату, используя часовой пояс по умолчанию (который я установил в EST), прежде чем он сохранит ее. Но TIMESTAMP не должен всегда автоматически сохраняться в UTC. Документация MySQL гласит: MySQL преобразует значения TIMESTAMP из текущего часового пояса в UTC для хранения и обратно из UTC в текущий часовой пояс для получения. (выпуск 1).
Наконец, для третьей строки я использовал pst.setTimestamp(2, t, utc.getCalendar());
для хранения даты с надеждой, что водитель должен использовать часовой пояс UTC. Но, видимо, нет (выпуск 2).
Я легко могу решить проблему сохранения дат в UTC, установив часовой пояс по умолчанию в UTC. Но все же я хотел бы понять, что происходит для двух вышеуказанных вопросов.