useTimezone是较旧的解决方法。 MySQL团队最近重写了setTimestamp / getTimestamp代码,但只有在连接参数useLegacyDatetimeCode = false并且使用最新版本的mysql JDBC连接器时,才会启用它。所以例如:
String url =
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false
如果您下载mysql-connector源代码并查看setTimestamp,那么很容易看到发生了什么:
如果使用legacy date time code = false,则调用newSetTimestampInternal(…)。然后,如果传递给newSetTimestampInternal的日历为NULL,则日期对象将在数据库的时区中格式化:
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).
… NOT setTimestamp(int,Timestamp,Calendar)。
现在应该明白这是如何工作的。如果您建立日期:2011年1月5日上午3:00在美国/ Los_Angeles(或任何你想要的时区)使用java.util.Calendar并调用setTimestamp(1,myDate),那么它将占用你的日期,使用SimpleDateFormat在数据库时区格式化它。所以如果你的数据库在美国/纽约州,那么它将构造要插入的字符串’2011-01-05 6:00:00′(因为纽约在3小时之前是洛杉矶)。
要检索日期,请使用getTimestamp(int)(不含Calendar)。再次使用数据库时区来建立日期。
注意:网络服务器时区现在完全不相关了!如果不将useLegacyDatetimecode设置为false,则Web服务器时区用于格式化 – 增加了许多混乱。
注意:
这可能是MySQL我抱怨服务器时区是不明确的。例如,如果您的数据库设置为使用EST,Java中可能会有几个可能的EST时区,因此您可以通过详细说明数据库时区是什么来澄清这一点:
String url =
"jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false&serverTimezone=America/New_York";
你只需要这样做,如果它抱怨。