这个问题具体是关于未来的日期和时间(对于过去的值,UTC无疑是首选)。
我想知道是否有人对最好的"在MySQL数据库中保存将来日期和时间的方法(或者通常 ),特别是在列可以保留来自不同时区的时间的上下文中。考虑到时区规则可能会改变UTC可能不是最佳选择。
我到目前为止找到的最可行的选项是将其保存为位置当地时间的文本以及位置(例如" America / *")。不幸的是,这种解决方案可能更容易出现数据损坏,并且绝对不太方便计算。
有人能想到更好的东西吗?
提前致谢
答案 0 :(得分:2)
保存未来日期戳的注意事项与过去的日期戳明显相同。
(我称之为 datestamps ,因为DATETIME
和TIMESTAMP
都是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)
首先,我之前已经详细介绍了这一点,所以请阅读我的答案here和here,以及this blog post by Lau Taarnskov。
特别关注MySQL,您通常不希望将TIMESTAMP
字段用于未来事件的本地时间,因为它会从会话的时区转换为UTC在写入时,并在读取时从UTC转换回会话的时区。即使这些是相同的时区ID(他们不必这样),也不能保证时区数据在一个或两个时区之间不会发生变化。你写的数据和事件发生的时间。
相反,请使用DATETIME
字段,该字段不会进行隐式时区转换。你得到了你所写的确切价值。存储事件的本地时间,并存储包含事件时区标识符的VARCHAR
字段。这是保留用户原始意图的唯一方法。
基本情况和边缘情况都在我之前给出的答案中描述。