java - MySQL:由于时区,表中的日期值与选择结果中的值不同
问题描述
我正在运行一个基于 java 的应用程序,它使用 JDBC 连接器访问 MySQL。
如果我在 MySQL Workbench 中运行此选择(类型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
有时间?
更新
MySQL服务器版本:5.7.20
JDBC 连接器版本:8.0.13
根据这里他们是兼容的
解决方案
任何想法可能会发生什么?
夏令时。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
andjava.time.LocalDateTime
代替。
推荐阅读
- filemaker - 条件语句技术
- python - Python - CSV 到 dict - 键中的 unicode 字符
- r - 在 R 中使用 Likert 包抑制或删除因子水平以改进分析
- c# - C# Timer:在周期性任务运行时将间隔更改为无限
- html - Flex/CSS 无法在 div 的中心对齐文本
- google-apps-script - Google Calendar API V3 - 如何将定期事件复制到其他日历?
- javascript - Ajax 异步发布
- python - 根据另一个键过滤字典列表以删除一个键中的重复项
- angular - 我的核心模块如何导出另一个模块?
- jenkins - 在 Jenkins 中工作时如何在 Robot Framework 中设置默认下载目录