首页 > 解决方案 > Java:Mysql时间戳夏令时错误

问题描述

我在 mysql 中有一个特定的表,其字段refresh_time Typetimestamp.

在我的代码中,我将该refresh_time字段更新为下个月的未来日期。为此,我使用以下逻辑计算下个月日期的毫秒数:

periodRefresh = currentTime + MyServiceUtils.calculateNoOfDaysInMonth(currentTime)*86400000L;

然后periodRefresh (milliseconds)我转换为的值并将其java.sql.Timestamp传递给数据库端以更新字段:

new Timestamp(periodRefresh);

但是发生的事情是 db 中的当前日期是2021-04-03 15:57:13,当运行上述逻辑以将时间更新到下个月时,它同时更新了2021-05-03 13:57:13比预期时间少 2 小时的时间。

我们的服务器遵循 UTC 时区,但我看到用户来自澳大利亚,那天(2021 年 4 月 4 日)在 AEST 有夏令时。但即便如此,它并没有像我转换2021-04-03 15:57:13 UTC为 AEST 一样添加到上面,它出现2021-04-03 01:57:13在凌晨 3 点的夏令时。

以上所有内容使我对以下问题感到有些困惑:

标签: javamysqldatetimetimestamp

解决方案


在 MySQL 中,TIMESTAMP数据类型总是以 UTC 格式存储在表中。当您将它们放入数据库时​​,它首先将它们从您的连接time_zone设置转换为 UTC。当你检索它们时,它会以另一种方式翻译它们。这不适用于DATETIME数据类型。

如果您有一个全局应用程序,则此TIMESTAMP行为很方便。您可以询问每个用户的首选时区,并将其存储为用户偏好设置。

如果您采用原始(UTC 中的 UNIX 纪元以来的秒数)TIMESTAMP值并将一个月的秒数添加到其中,则生成的时间戳值可能处于不同的夏令时状态。所以会有不同的翻译。

任何一个

  1. 在 MySQL 中进行时间戳处理,例如使用

    UPDATE tbl SET periodRefresh = periodRefresh + INTERVAL 1 MONTH;
    
  2. 在您的应用程序中完成所有操作并使用DATETIME, not TIMESTAMP, 数据类型(以避免数据库的时区转换,或

  3. 在您的应用程序中完成所有操作并使用SET time_zone='UTC';在每个连接上。


推荐阅读