数据库
首页 > 数据库> > 如何在脚本中处理MySQL时区

如何在脚本中处理MySQL时区

作者:互联网

我正在开发一个移动应用程序.从应用程序调用到基于模式(?mode = xx)运行不同查询的Web服务.

在其中一些查询中,我使用DATE(NOW())之类的日期函数.

MySQL数据库中存储的数据存储在GMT-7(加拿大山地时间)中.

我尚未为该Web服务注册域/主机,但是当我这样做时,可以说它托管在另一个城市中,例如多伦多(格林尼治标准时间5-2小时).然后在加拿大山区时间晚上10:05,用户使用该应用程序发送网络查询呼叫,该查询具有以下查询:

SELECT DATE(NOW()) 

由于服务器托管在多伦多,因此即使用户位于前一天,该应用程序也会根据明天显示日期,而该日期将返回明天的日期.

有人对此有任何想法吗?

编辑:

SYSTEM
2015-01-29 16:19:48
2015-01-29 23:19:48

是运行查询的结果select @@ time_zone,now(),utc_timestamp()

查询处理日期(yyyy-mm-dd)和时间(hh:mm:ss)列类型.

解决方法:

您在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和DATETIME都是时区忽略的.保存日期/时间值后,即使您更改了时区设置,也将获得相同的值.

TIMESTAMP数据类型是时区敏感的.这些数据项始终存储在UTC, also known as Z, time中,以前称为格林威治标准时间.它们在存储时总是转换为UTC,而在检索时总是转换回.

用于获取当前日期和时间(NOW()和朋友)的builtin functions是时区敏感的.他们将在当地时间产生值.例外情况是三个以UTC_开头的函数,它们以UTC时间产生值.

许多MySQL多时区应用程序都遵循以下操作准则:

>向每个用户询问用户偏好的时区,或从有关该用户的其他个人数据中找出该时区. (电话已从网络向电话提供了此信息.)代表用户将其存储为zoneinfo-friendly时区描述符(“美国/纽约州”,“加拿大/山地”,“欧洲/维也纳”等).
>在代表用户建立MySQL会话后,使用设置的time_zone查询(如上所示)设置用户的时区.您应该在连接操作之后立即执行此操作.
>将用户的日期和时间存储到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之后立即陷入死机.

标签:mysql,timezone,datetime,unix-timestamp,datetime-conversion
来源: https://codeday.me/bug/20191014/1911979.html