我正在运行一个基于java的应用程序,使用JDBC连接器访问MySQL。
如果我在MySQL Workbench中运行这个select(其中per_date_from
的类型是DATE
):
select per_date_from from formulas;
我得到一行:
1993-05-27
现在,如果我运行这个Java代码:
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select per_date_from from formulas");
while (rs.next()) {
java.sql.Date d = rs.getDate(1);
System.out.println("d=" + d);
java.sql.Timestamp ts = rs.getTimestamp(1);
System.out.println("ts=" + ts);
}
我在控制台中得到了这个结果:
09:35:51,412 INFO [stdout] (default task-2) d=1993-05-26
09:35:51,412 INFO [stdout] (default task-2) ts=1993-05-26 23:00:00.0
Java代码和MySQL Workbench在连接中都有以下选项:
serverTimezone=America/New_York
到底是怎么回事?为什么列类型DATE
有时间?
UPDATE
MySQL服务器版本:5.7.20
JDBC连接器版本:8.0.13
根据here他们是兼容的
有什么想法会发生什么?
夏令时。 serverTimezone=America/New_York
告诉MySQL Connector / J使用该时区,它观察DST。但是,您的JVM使用的是GMT-05:00
,它是固定的偏移量,不会观察到DST。因此,如果MySQL DATE碰巧是在纽约东部夏令时期间,那么Timestamp
将是一小时关闭...
sql = "SELECT CAST('1993-05-27' AS DATE)";
ResultSet rs = st.executeQuery(sql);
rs.next();
Timestamp t = rs.getTimestamp(1);
System.out.println(t); // 1993-05-26 23:00:00.0
...如果日期是在纽约东部标准时间期间,那么Timestamp
将包含正确的日期:
sql = "SELECT CAST('1993-01-27' AS DATE)";
ResultSet rs = st.executeQuery(sql);
rs.next();
Timestamp t = rs.getTimestamp(1);
System.out.println(t); // 1993-01-27 00:00:00.0
故事的道德启示:
停止使用java.sql.Timestamp
。对于不包含时区信息的DATE和DATETIME等列类型,请改用java.time.LocalDate
和java.time.LocalDateTime
。