您在 MySQL 服务器上运行了此时间诊断查询。
select @@time_zone, now(), utc_timestamp()
从你的本地时间和UTC时间可以清楚地看出,你的服务器机器的系统时区设置是“加拿大/山地”,并且MySQL服务器软件没有自己的时区设置。
如果您拿起表格并将它们原封不动地移动到某个附近时区的服务器,您可以始终更新您的软件以发出命令
set time_zone = 'Canada/Mountain';
从软件连接后即可。这将使您的新 MySQL 连接在时区方面与当前连接的行为类似。如果您拥有 MySQL 服务器,则可以根据本页上的说明设置其默认时区。http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html
现在,这是关于时间数据类型的故事。DATE
, TIME
, and DATETIME
都是时区不可知。一旦您存储了日期/时间值,即使您更改了时区设置,您也会得到相同的值。
The TIMESTAMP
数据类型是时区敏感。这些数据项始终存储在UTC,也称为 Z 时间,以前称为格林威治标准时间。它们在存储时始终转换为 UTC,并在检索时始终转换回来。
The 内置函数用于获取当前日期和时间(NOW()
和朋友)是时区敏感。他们将在当地时间产生值。例外情况是以下三个函数:UTC_
产生 UTC 时间的值。
许多 MySQL 多时区应用程序使用以下操作规则:
- 询问每个用户用户偏好的时区,或者从有关用户的其他一些个人数据中找出它。 (电话已从网络提供此信息。)将其存储为区域信息友好代表用户的时区描述符(“美国/纽约”、“加拿大/山区”、“欧洲/维也纳”等)。
- 代表用户建立 MySQL 会话后,设置用户的时区
set time_zone
查询如上所示。您应该在您之后立即执行此操作connect
手术。
- 将用户的日期和时间存储到
TIMESTAMP
数据类型。它们在存储时会转换为 UTC。
- 根据需要检索它们。他们将被转换回当地时间。
这个想法是用户的时区是她的上下文的一部分。这很有效,因为如果用户 A 在温哥华而用户 B 在哈利法克斯,并且由于某种原因用户 B 查看用户 A 的时间数据,则该数据将或多或少自动以大西洋时间显示给 B。
它的另一个好处是它可以透明地处理全球变幻莫测的夏令时到标准时间的变化。去年夏天的时间戳将以去年夏天的当地时间显示。
许多全球使用的服务器管理员将其系统服务器时间或 MySQL 默认时区设置为 UTC。 (你的没有。)
处理这一切的另一种方法是你开始的方式。选择一个时区并存储与该时区相关的时间戳。在这种情况下,最好选择不在夏令时和标准时间之间交替的时区。然后,将时间存储到数据库时,进行显式转换。您可以通过执行类似的操作来存储渥太华用户的时间。
INSERT INTO tbl (appt) VALUES ( 'whatever-time' - INTERVAL 120 MINUTE)
你会以同样的方式得到这些值。这很容易出错,但你可以让它工作。
最后,您可以自己进行转换。
如果您想知道某个任意时区与 UTC 之间有多少分钟的偏移量,请尝试这两个查询。
set time_zone = 'Canada/Atlantic';
select timestampdiff(minute, utc_timestamp(), now());
每年的这个时候返回 -240,即 -4:00。由于某些国家/地区存在半小时或刻钟时区偏移,因此您需要使用分钟而不是小时。
最后,要小心。TIMESTAMP
数据类型不代表 1970 年之前的时间。而且,在我的 MariaDB 10.0 实例上,当时间超出 32 位时,它似乎在 2038-01-19T03:14:07 UTC 之后就陷入了地狱。