首页 > 解决方案 > 检索和插入日期时间时,MYSQL 的默认行为是什么?遇到一个有趣的时区偏移问题

问题描述

我们在测试环境中有一个 UTC 时区的服务器,并注意到 PDT 中的时间显示不正确。

我们提出的解决方案是在将所有内容存储到数据库之前将其转换为 UTC 时间,然后在检索时使用 moment-timezone 将其转换回正确的语言环境时区。

我遇到了一个有趣的问题,即 UTC 时区转换工作正常(例如,如果事件发生在太平洋夏令时间上午 8:00,它会将其存储为 15:00 UTC,正确时差为 +7 小时)。所有转换都发生在客户端,然后作为字符串传递到服务器,直到最终存储到数据库中。在数据库中运行查询后,我以正确的 15:00 格式看到它。

但是,当我检索数据时,它会增加 7 小时并返回 22:00。我已经在所有控制器路由上记录了这一点,并确认服务器上任何地方的日期对象都没有发生其他额外的修改,所以我假设这是我需要注意的 MYSQL 的默认行为是否正确的?

有没有人知道为什么会发生这种情况?

使用 moment-timezone 将本地客户端时间转换为 UTC 并将其存储为字符串。将此传递给控制器​​以插入数据库。

已确认的数据库正在按预期正确存储信息。

增加了 7 小时以上的输出不正确。

// This is on the client side where it formats the date using moment to convert it to UTC from locale time
function convertTimeToUTCTimezone(date) {
  const timezone = "America/Vancouver"; // TODO make this more applicable across different time zones in the future

  const formatDate = moment(date).format('YYYY-MM-DD HH:mm:ss');
  const formatTimezoneDate = moment.tz(formatDate, 
  timezone).utc().format('YYYY-MM-DD HH:mm:ss');
  return formatTimezoneDate;
}

输入表格的日期为:2019-06-14 8:00:00(太平洋夏令时间上午 8 点,即 UTC - 7 小时)

从客户端传递到服务器的日期字符串为:2019-06-14T15:00:00.000Z

我希望通过 MySQL 查询看到的日期时间是:(正确)2019-06-12 15:00:00

我希望从中检索到的时间等于:(预期)2019-06-14T15:00:00.000Z

但我得到:(问题)2019-06-14T22:00:00.000Z

[更新] mysql 数据库,列定义为 DATETIME

插入示例:

// Using objectionJS
static async function insertToTable(formData) {
  // formData is an object of key-value pairs, keys matching database column names
  return this.query().insert(formData);
}

标签: mysqlnode.jstimezonemomentjs

解决方案


我很好奇实际 MySQL“INSERT”语句中“Date/Time”列的值是什么样的。我也很好奇您在 MySql 表中定义的类型。

一般来说,我会推荐:

  • 将日期、时间和日期时间列定义为“DATETIME”类型

  • 如果可能,设置默认约束并为您的 INSERT 使用“NOW()”。这将使用服务器的日期/时间/时区。

从这个链接:

https://www.vertabelo.com/blog/technical-articles/the-proper-way-to-handle-multiple-time-zones-in-mysql

一个完整的通用方法是使用两个 DATETIME 列来存储 utc_datetime 和 local_datetime,而 VARCHAR 列存储 IANA time_zone 字符串(目前最长的是“America/Argentina/ComodRivadavia”,它有 32 个字符)。

无论你决定什么,我都会考虑在 MySql/服务器端做大部分的“工作”,而不是在你的 Javascript 客户端。


推荐阅读