如何将java.util.Date存储在UTC / GMT时区的MySQL时间戳字段中?
我使用了一个新的Date()对象来填充MySQL数据库中的字段,但该字段中存储的实际值是我的本地时区。
如何配置MySQL以将其存储在UTC / GMT时区?
我认为,配置连接字符串会有所帮助,但我不知道如何操作。连接字符串中有许多属性,例如 useTimezone、serverTimzone、useGmtMillisForDatetimes、useLegacyDatetimeCode、...
我使用了一个新的Date()对象来填充MySQL数据库中的字段,但该字段中存储的实际值是我的本地时区。
如何配置MySQL以将其存储在UTC / GMT时区?
我认为,配置连接字符串会有所帮助,但我不知道如何操作。连接字符串中有许多属性,例如 useTimezone、serverTimzone、useGmtMillisForDatetimes、useLegacyDatetimeCode、...
简短的回答是:
使用 JDBC 获取/设置日期或时间戳时,请始终使用 Calendar 参数,设置为 UTC:
resultset.getTimestamp(“my_date”, Calendar.getInstance(TimeZone.getTimeZone(“UTC”)));
长答案是这样的:
在处理任何数据库中的日期和时区以及任何客户端代码时,我通常建议使用以下策略:
将数据库配置为使用 UTC 时区,而不是使用服务器的本地时区(当然,除非它是 UTC)。
如何执行此操作取决于您的数据库服务器。可以在此处找到MySQL的说明:http://dev.mysql.com/doc/refman/5.0/en/time-zone-support.html。基本上你需要在my.cnf中写这个:default-time-zone=utc
通过这种方式,您可以在任何地方托管数据库服务器,轻松更改托管位置,并且更普遍地操作服务器上的日期,而不会有任何歧义。
在应用程序代码中,始终使用 UTC 日期,除非向用户显示日期。
Timestamp myDate = resultSet.getTimestamp(“my_date”, Calendar.getInstance(TimeZone.getTimeZone(“UTC”)));
同步服务器或仅依赖数据库服务器的时间
如果您的 Web 服务器位于一台(或多台)服务器上,数据库服务器位于其他服务器上,那么我强烈建议您将它们的时钟与 NTP 同步。
或者,只依靠一台服务器来告诉你现在是什么时间。通常,数据库服务器是请求时间的最佳服务器。换句话说,避免这样的代码:
preparedStatement = connection.prepareStatement(“UPDATE my_table SET my_time = ?其中[...]“);
java.util.Date now = new java.util.Date();当地时间!:-(
preparedStatement.setTimestamp(1, new Timestamp(now.getTime()));
int result = preparedStatement.execute();
preparedStatement = connection.prepareStatement(“UPDATE my_table SET my_time = NOW() WHERE [...]”);
int result = preparedStatement.execute();
希望这有帮助!:-)
MiniQuark总体上为数据库提供了一些很好的答案,但是有一些MySql特定的怪癖需要考虑......
将数据库配置为使用 UTC 时区
这实际上不足以解决问题。如果按照 OP 的要求将 java.util.Date 传递给 MySql,则 MySql 驱动程序将更改该值,使其看起来像数据库时区中的相同本地时间。
示例:您的数据库(如果配置为 UTC)。您的应用程序是 EST。您将 java.util.Date 对象传递给 5:00 (EST)。数据库会将其转换为 5:00 UTC 并存储它。棒。
在传递数据以“撤消”此自动调整之前,您必须调整时间。像这样...
long originalTime = originalDate.getTime();
Date newDate = new Date(originalTime - TimeZone.getDefault().getOffset(originalTime));
ps.setDate(1, newDate);
读回数据需要类似的转换。
long dbTime = rs.getTimestamp(1).getTime();
Date originalDate = new Date(dbTime + TimeZone.getDefault().getOffset(dbTime));
这是另一个有趣的怪癖...
在Java中,当从数据库中读取时,始终使用:Timestamp myDate = resultSet.getTimestamp(“my_date”, Calendar.getInstance(TimeZone.getTimeZone(“UTC”)));
MySql实际上忽略了该日历参数。这将返回相同的值,而不管您传递哪个日历。