问题描述
遇到一个问题,mysql时区和客户端时区不一致,导致读出来的时间戳错误,表现为数据库中的年月日时分秒+客户端的时区。正常应该是数据库的年月日时分秒+数据库的时区。
问题复现
mysql
mysql版本5.5.62,timezone=-08:00
CREATE TABLE `test` (
`id` int(11) DEFAULT NULL,
`releaseTime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
client
客户端时区+08:00
jdbc.driverClassName =com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3307/test
jdbc.username = root
jdbc.password = root
public class DBConnTest {
public static void main(String[] args) throws SQLException {
Connection conn = DBConnection.getConnection("jdbc.properties");
String sql = "select * from test";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
Timestamp releaseTime = rs.getTimestamp("releaseTime");
System.out.println(releaseTime);
}
}
}
执行结果如下:2020-08-28 03:25:21.0
源码跟踪
debug模式进入jdbc源码,如果没有设置useLegacyDatetimeCode,默认值是true,默认时区就是客户端时区,如果设置为fasle就是服务器时区。
this.connection.getDefaultTimeZone()
是+08:00
,this.serverTimeZoneTz
是-08:00
这个函数是最终生成时间戳的地方,tz是上面的默认时区,年月日时分秒是从数据库中读出来的。
如果时区是客户端时区,而且和服务器时区不同,那就会出错。
读出的正确时间是:2020-08-28 19:25:21.0
如果设置useTimezone=true
也能得到正确时间,如下,tstamp已经拼错了,数据库年月日时分秒+客户端时区,下面代码硬生生修正了。
结论
jdbc url后面设置:useLegacyDatetimeCode=false
(这个更好)或useTimezone=true