如何在数据库中保存未来(!)日期

时间:2017-04-22 10:59:31

标签: mysql datetime database-design time timezone

这个问题具体是关于未来的日期和时间(对于过去的值,UTC无疑是首选)。

我想知道是否有人对最好的"在MySQL数据库中保存将来日期和时间的方法(或者通常 ),特别是在列可以保留来自不同时区的时间的上下文中。考虑到时区规则可能会改变UTC可能不是最佳选择。

我到目前为止找到的最可行的选项是将其保存为位置当地时间的文本以及位置(例如" America / *")。不幸的是,这种解决方案可能更容易出现数据损坏,并且绝对不太方便计算。

有人能想到更好的东西吗?

提前致谢

2 个答案:

答案 0 :(得分:2)

保存未来日期戳的注意事项与过去的日期戳明显相同。

(我称之为 datestamps ,因为DATETIMETIMESTAMP都是MySQL中的保留字。为了便于讨论,我想要一个并不意味着的词数据类型。)

如果您要构建一个供多个时区的人使用的系统,最好向每个用户询问她的时区偏好,并将其存储在她的用户个人资料中。然后,当她登录时,您可以检索它,然后执行

  SET time_zone = 'America/Halifax'

或其他,命名用户的时区偏好。

如果您的MySQL服务器在Linux,BSD或其他* nix系统上运行,则这些时区来自该计算机上的zoneinfo subsystem。当各个国家的司法管辖区改变时区规则时,zoneinfo会更新。维护流行发行版的人会定期将更新推送到zoneinfo,因此您可以合理地更新。 (如果您的MySQL服务器在Windows主机上运行,​​请在该操作系统上阅读有关MySQL时区内容的一些内容。让事情保持最新是一件麻烦事。)

然后,如果对日期戳使用TIMESTAMP数据类型,则每次检索值时,它都会在显示之前自动从UTC转换为本地时区。每次存储值时,它都会自动转换为UTC。在这方面,NOW()值与时间戳类似。例如,如果你做了

 UPDATE appointment
    SET datestamp = NOW() + INTERVAL 7 DAY
  WHERE id = something

您将在此时间后的一周内存储UTC时间。如果你这样做

SELECT datestamp
  FROM appointment
 WHERE id = something

用户将在SET timezone设置的本地时区中查看时间。

如果对日期戳使用DATETIME数据类型,则可以在存储和检索时自行抵消它们。存储它们时,将它们从本地时区偏移到UTC。当你检索它们时,走另一条路。 Use CONVERT_TZ() for that

 UPDATE appointment 
    SET datestamp = CONVERT_TZ(NOW(), 'America/Halifax', 'UTC') + INTERVAL 7 DAY
  WHERE id = something

SELECT CONVERT_TZ(datestamp, 'UTC', 'America/Halifax') datestamp
  FROM appointment
 WHERE id = something

显然,在这些查询中用'America/Halifax'替换用户选择的时区。

如果您可能会避免,请参考从夏令时变为标准时间的本地时间来存储您的日期戳。如果您这样做,您将在应用程序生命周期的转换日期间持续出现故障。我知道这是因为我已经继承了一些以这种方式工作的系统。馊主意。 UTC:好主意。

答案 1 :(得分:2)

首先,我之前已经详细介绍了这一点,所以请阅读我的答案herehere,以及this blog post by Lau Taarnskov

特别关注MySQL,您通常不希望将TIMESTAMP字段用于未来事件的本地时间,因为它会从会话的时区转换为UTC在写入时,并在读取时从UTC转换回会话的时区。即使这些是相同的时区ID(他们不必这样),也不能保证时区数据在一个或两个时区之间不会发生变化。你写的数据和事件发生的时间。

相反,请使用DATETIME字段,该字段不会进行隐式时区转换。你得到了你所写的确切价值。存储事件的本地时间,并存储包含事件时区标识符的VARCHAR字段。这是保留用户原始意图的唯一方法。

基本情况和边缘情况都在我之前给出的答案中描述。

相关问题