首页 > 解决方案 > MySQL:由于时区,表中的日期值与选择结果中的值不同

问题描述

我正在运行一个基于 java 的应用程序,它使用 JDBC 连接器访问 MySQL。

如果我在 MySQL Workbench 中运行此选择(类型per_date_fromDATE):

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

根据这里他们是兼容的

标签: javamysqljdbc

解决方案


任何想法可能会发生什么?

夏令时。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.LocalDateandjava.time.LocalDateTime代替。


推荐阅读