如何使用 Java 更改数据库连接中的 MySQL 时区?

新手上路,请多包涵

MySQL 运行时区为“GMT+8”,而 Tomcat 运行时区为“GMT”。当我将 日期 时间保存到我的数据库时,一切似乎都正常,但是当我检查数据库中的 日期 时间值时,我看到了“GMT”值。

此外,当我尝试从数据库中获取值时,值发生了变化,似乎数据库中的值被视为“GMT+8”,因此 Java 将值更改为“GMT”。

我已经像这样设置了连接 URL:

 useTimezone=true&serverTimezone=GMT

但它不起作用。

原文由 Xilang 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 698
2 个回答

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(整数、时间戳、日历)。

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

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

注意: 网络服务器时区现在完全不相关! 如果您不将 useLegacyDatetimecode 设置为 false,则网络服务器时区用于格式化 - 增加很多混乱。


笔记:

MySQL 可能会抱怨服务器时区不明确。例如,如果您的数据库设置为使用 EST,Java 中可能有多个可能的 EST 时区,因此您可以通过准确地告诉 mysql-connector 数据库时区是什么来澄清这一点:

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

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

原文由 nogridbag 发布,翻译遵循 CC BY-SA 3.0 许可协议

JDBC 使用所谓的“连接 URL”,因此您可以通过“%2B”对“+”进行转义,即

useTimezone=true&serverTimezone=GMT%2B8

原文由 Jay 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题