MySQL的时区为"GMT+8",而Tomcat的时区为"GMT".当我将datetime保存到数据库时,一切似乎都正常,但当我判断数据库中的datetime值时,我看到了"GMT"值.
另外,当我try 从数据库中获取值时,值被更改,似乎数据库中的值被视为"GMT+8",所以Java将值更改为"GMT".
我将连接URL设置为:
useTimezone=true&serverTimezone=GMT
但它不起作用.
MySQL的时区为"GMT+8",而Tomcat的时区为"GMT".当我将datetime保存到数据库时,一切似乎都正常,但当我判断数据库中的datetime值时,我看到了"GMT"值.
另外,当我try 从数据库中获取值时,值被更改,似乎数据库中的值被视为"GMT+8",所以Java将值更改为"GMT".
我将连接URL设置为:
useTimezone=true&serverTimezone=GMT
但它不起作用.
useTimezone是一个较老的解决方案.MySQL团队最近重写了setTimestamp/getTimestamp代码,但只有在设置连接参数useLegacyDatetimeCode=false并且使用最新版本的MySQL JDBC连接器时,才会启用该代码.例如:
String url =
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false
如果下载mysql连接器源代码并查看setTimestamp,很容易看到发生了什么:
如果use legacy date time code=false,则newSetTimestampInternal(…)被称为.然后,如果传递给newSetTimestampInternal的日历为空,则日期对象将在数据库的时区中格式化:
this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US);
this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ());
timestampString = this.tsdf.format(x);
日历为空非常重要,因此请确保使用:
setTimestamp(int,Timestamp).
... 不设置时间戳(int、Timestamp、Calendar).
现在应该很清楚这是怎么回事了.如果你用java构建一个日期:2011年1月5日凌晨3:00在美国/洛杉矶(或任何你想要的时区).util.Calendar和call setTimestamp(1,myDate),然后它将记录您的日期,使用SimpleDateFormat将其格式化为database time zone.因此,如果您的DB位于美国/纽约,它将构造要插入的字符串"2011-01-05 6:00:00"(因为纽约领先洛杉矶3小时).
要检索日期,请使用getTimestamp(int)(不带日历).它将再次使用数据库时区来创建日期.
注意:The webserver time zone is completely irrelevant now!如果不将useLegacyDatetimecode设置为false,则webserver时区用于格式化,这会增加很多混乱.
注:
我可能会抱怨服务器时区不明确.例如,如果您的数据库设置为使用EST,那么Java中可能有几个EST时区,因此您可以通过告诉mysql connector数据库时区是什么来澄清这一点:
String url =
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false&serverTimezone=America/New_York";
只有当它抱怨时,你才需要这样做.