2017-04-22 98 views
1

这个问题是关于未来的日期和时间(过去的值无疑是第一选择)。如何将未来(!)日期保存在数据库中


我不知道是否有人曾建议以“最佳”的方式保存在MySQL数据库中的未来日期和时间(或为此事也一般),特别是在列可以保存来自不同时区的时间的上下文。考虑到时区规则可能会改变UTC可能不是最好的选择。

到目前为止,我发现的最可行的选择是将它作为文本保存在位置当地时间以及位置(例如“America/*”)中。不幸的是,这个解决方案可能更容易发生数据损坏,对于计算而言绝对不方便。

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

在此先感谢

+0

“考虑到时区的规则可能改变UTC可能不是最好的选择” - 我不能按照你的逻辑。任意时区的立法恰恰是UTC的一个论据。 –

+0

@ÁlvaroGonzález--它不那么简单。如果事件是在上午10点在7月1日在埃及开罗在2027年,我不能告诉你现在什么UTC时间,这将是,因为这将需要对我而言这样的假设:埃及政府不会改变自己的时区现在和之后的规则。事实上,这已在过去[埃及特别](http://codeofmatt.com/2016/07/01/time-zone-chaos-inevitable-in-egypt/)和[其他时区的问题有一些规律性](http://codeofmatt.com/2016/04/23/on-the-timing-of-time-zone-changes/)。 –

回答

2

保存未来日戳的考虑是几乎一样的过去日戳。

(我称他们为日戳因为无论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'

如果您可能可以避免IT不参考当地时间存储您的日期戳从夏时制改为标准时间。如果你这样做,你的应用程序的整个生命周期的转换日将会持续出现问题。我知道这一点,因为我继承了一些以这种方式工作的系统。馊主意。 UTC:好主意。

+1

关于时间处理看到如此清晰无误的解释并不常见。 –

+1

我说'DATETIME'就像是拍一张时钟的照片;你无法分辨TZ涉及什么。 –

+1

这是放置它的好方法。麻烦的是,'TIMESTAMP'在2038年初发布,除非它们改变磁盘格式。 –

1

首先,我之前已经详细地写过这篇文章,所以请阅读我的答案herehere以及this blog post by Lau Taarnskov

针对MySQL,您通常不希望在将来事件的本地时间使用TIMESTAMP字段,因为它将在写入时从会话的时区转换为UTC,并从UTC转换回UTC在读取时刻到会话的时区。即使这些都是同一个时区的IDS(他们不必须的),但也不能保证该时区的数据将不会为一个或两个时区,当你写数据,并在事件之间切换发生。

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

理由和边缘情况在我以前给了答案,所有描述。

相关问题