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

Mysql 如何在数据库中保存未来(!)日期,mysql,datetime,database-design,time,timezone,Mysql,Datetime,Database Design,Time,Timezone,这个问题特别是关于未来的日期和时间(对于过去的值,UTC无疑是首选) 我想知道是否有人对在MySQL数据库中保存未来的日期和时间的“最佳”方法提出了建议(或者对于这一点,通常也是如此),特别是在该列可以保存来自不同时区的时间的上下文中。考虑到时区规则可能会改变,UTC可能不是最佳选择 到目前为止,我找到的最可行的选择是将其与地点(例如“America/*”)一起保存为地点当地时间的文本。不幸的是,此解决方案可能更容易发生数据损坏,并且对计算肯定不太方便 有人能想出更好的吗 提前感谢保存未来的邮

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



我想知道是否有人对在MySQL数据库中保存未来的日期和时间的“最佳”方法提出了建议(或者对于这一点,通常也是如此),特别是在该列可以保存来自不同时区的时间的上下文中。考虑到时区规则可能会改变,UTC可能不是最佳选择

到目前为止,我找到的最可行的选择是将其与地点(例如“America/*”)一起保存为地点当地时间的文本。不幸的是,此解决方案可能更容易发生数据损坏,并且对计算肯定不太方便

有人能想出更好的吗


提前感谢

保存未来的邮戳的注意事项与保存过去的邮戳的注意事项基本相同

(我之所以称之为datestamps,是因为
DATETIME
TIMESTAMP
都是MySQL中的保留字。为了便于讨论,我想要一个不包含任何数据类型的字。)

如果您正在构建一个供多个时区的用户使用的系统,最好询问每个用户的时区偏好,并将其存储在她的用户配置文件中。然后,当她登录时,你可以检索它,然后

  SET time_zone = 'America/Halifax'
或者,命名用户的时区偏好

如果您的MySQL服务器运行在Linux、BSD或其他*nix系统上,则这些时区来自该机器上的。当不同的国家管辖区更改时区规则时,zoneinfo会得到更新。维护流行发行版的人通常会将更新推送到zoneinfo,这样您就可以合理地了解最新情况。(如果您的MySQL服务器运行在Windows主机上,请阅读该操作系统上有关MySQL时区的内容。让事情保持最新更麻烦。)

然后,如果对日期戳使用
时间戳
数据类型,则在检索值时,该值会在显示之前自动从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。当你找回它们时,走另一条路

显然,在这些查询中,将用户选择的时区替换为
“America/Halifax”


如果可以避免的话不要参考从夏时制更改为标准时间的当地时间来存储日期戳。如果您这样做,在应用程序的生命周期中,您将在转换日遇到持续的小故障。我之所以知道这一点,是因为我继承了几个这样运作的系统。坏主意。UTC:好主意。

首先,我之前已经详细介绍了这一点,所以请阅读我的答案,以及

对于MySQL,您通常不希望为未来事件的本地时间使用
时间戳
字段,因为它将在写入时从会话时区转换为UTC,在读取时从UTC转换回会话时区。即使这些是相同的时区ID(它们不一定是),也不能保证在写入数据和事件发生之间,其中一个或两个时区的时区数据不会发生更改

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


基本原理和边缘案例都在我之前给出的答案中进行了描述。

“考虑到时区规则可能会改变,UTC可能不是最佳选择”——我无法遵循您的逻辑。任意的时区立法正是UTC的一个论据。@阿尔瓦罗冈萨雷斯——并没有那么简单。如果2027年7月1日上午10点在埃及开罗举行活动,我现在无法告诉您UTC时间,因为这需要我假设埃及政府从现在起不会改变时区规则。事实上,这在过去一直是一个问题。对于时间处理的解释如此清晰和完美并不常见。我说,
DATETIME
就像给时钟拍照;你不知道TZ牵涉到什么,这是一个很好的表达方式。问题是,
TIMESTAMP
s将在2038年初用完,除非他们更改磁盘格式。@阿尔瓦罗冈萨雷斯-不幸的是,这个答案不清楚,也不完美。它很好地描述了
时间戳
日期时间
,但它没有解决眼前的问题。@O.Jones-UTC不适合安排未来事件。对不起,任何相反的建议都是有缺陷的。特别是,你最后一句避免非dst时区的话意味着你不应该在美国或欧洲的大部分地区安排活动。
 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