如何在java连接中更改mysql时区

Mysql在GMT + 8运行,但tomcat在GMT运行。 当将日期时间保存到数据库时,似乎运行正常,当我检查DB中的日期时间值时,我看到GMT值。 但是当我尝试从DB获取值时,值会更改,看起来DB中的值被视为GMT + 8,因此java将值更改为GMT。

我尝试设置连接url add

useTimezone=true&serverTimezone=GMT 

但不起作用

useTimezone是一种较旧的解决方法。 MySQL团队最近重写了setTimestamp / getTimestamp代码,但只有在设置连接参数useLegacyDatetimeCode = false并且使用最新版本的mysql JDBC连接器时才会启用它。 例如:

 String url = "jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false 

如果你下载mysql-connector源代码并查看setTimestamp,很容易看出发生了什么:

如果使用旧日期时间代码= false,则调用newSetTimestampInternal(…)。 然后,如果传递给newSetTimestampInternal的Calendar为NULL,则日期对象的格式为数据库的时区:

 this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US); this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ()); timestampString = this.tsdf.format(x); 

Calendar是空的非常重要 – 所以请确保您正在使用:

 setTimestamp(int,Timestamp). 

…不是setTimestamp(int,Timestamp,Calendar)。

现在应该很明显这是如何工作的。 如果您使用java.util.Calendar构建日期:2011年1月5日凌晨3:00在America / Los_Angeles(或您想要的任何时区)并调用setTimestamp(1,myDate),那么它将占用您的日期,使用SimpleDateFormat在数据库时区中格式化它。 因此,如果您的数据库位于America / New_York,它将构造要插入的字符串’2011-01-05 6:00:00’(因为纽约比LA早3小时)。

要检索日期,请使用getTimestamp(int)(不使用Calendar)。 它将再次使用数据库时区来构建日期。

注意: 网络服务器时区现在完全不相关! 如果未将useLegacyDatetimecode设置为false,则使用Web服务器时区进行格式化 – 增加了许多混淆。


注意:

MySQL可能会抱怨服务器时区不明确。 例如,如果您的数据库设置为使用EST,则Java中可能存在几个可能的EST时区,因此您可以通过告诉它确切的数据库时区来澄清这个问题:

 String url = "jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false&serverTimezone=America/New_York"; 

如果它抱怨,你只需要这样做。