Web和数据库服务器设置以获得UTC时区“正确”

问题描述:

我不知所措,试图做到这一点:我们有服务器位于十几个时区,其中Apache和MySQL运行在所有或部分时区,如以及在Amazon RDS上托管的MySQL。Web和数据库服务器设置以获得UTC时区“正确”

我想知道“最佳实践”,或者如何以其他方式配置每个MySQL和PHP安装,以便当从PHP添加一行到数据库时,我确信实际上这个值是UTC时间事件发生时,无论其中服务器发生何时发生。在任何给定的时区将其呈现给用户不是问题 - 我只想知道datetime列实际上是存储发生事件时的实际时刻。

现在,Web服务器被设置为任何本地时区是由于计划的事件等,我不知道该谜题的哪些部分使用哪些设置从哪里得出什么是写入数据库。

我很抱歉如果这个问题看起来不清楚,在这一点上我不知道我不知道什么,所以得到一个确切的问题甚至是具有挑战性的。此外,我们所有的日期都作为日期时间字段存储在数据库中,因此不可能存储时间戳。

如果您将自己限制为MySQL的DATE和DATETIME类型,则可以在很大程度上忽略MySQL本身中的时区问题。你要避免MySQL的TIMESTAMP类型,因为:

的MySQL从当前时区转换TIMESTAMP值以UTC进行存储,并从UTC回到当前时区进行检索。 (对于其他类型(如DATETIME),不会发生这种情况。)默认情况下,每个连接的当前时区是服务器的时间。

https://dev.mysql.com/doc/refman/5.7/en/datetime.html

至于读/写DATETIME值,你会得到你把什么的,这是很好的。

这留下了始终确保将UTC值写入数据库的问题。

确保PHP使用UTC的最佳方式是使用date_default_timezone_set()在应用程序中明确设置它。这将确保诸如date('Y-m-d H:i:s')之类的电话将为您提供UTC值。它也将确保像(new \DateTime('now'))->getTimezone()这样的东西将返回一个UTC \ DateTimeZone实例。

当然,当您存储从用户获取的日期/时间值时,事情会变得更加困难。在这些情况下,您需要以某种方式确定用户所在的时区,并在保存值之前处理到UTC的转换。假设你的用户有一些每个用户的时区设置,你基本上做的是这样的:

/** @var \DateTimeZone $userTZ */ 
$userTz = getUserTimezone(); 
$dateTime = new \DateTime($user_submitted_date_string, $userTz); 
$dateTime->setTimezone(new \DateTime('UTC')); 
$dateTimeStr = $dateTime->format('Y-m-d H:i:s'); 
+0

这就是我正在寻找的......“确保PHP使用UTC ...”,并且我/我们可以在应用程序级别控制它。只要我知道UTC正在进入数据库,其他一切都是小菜一碟。谢谢 – GDP

+0

最后一个问题......似乎MySQL中的默认时区对任何PHP都没有影响,除了使用NOW(),CURDATE()等的SQL之外。是这样吗? – GDP

+0

@GDP - 我很谨慎地做出这样的分类陈述。但我会说是。只要你避免依赖于MySQL内部默认时区设置的MySQL函数,你就很好。特别是,INSERT/SELECT行为与VARCHAR列的行为不可区分。 – timdev

非常简单,总是将unix time存储在数据库中(或者如果您希望microtime具有微秒精度)。然后,无论您的每个Web服务器的时区是多少,如果其中两个同时收到请求,它将是保存在数据库中的相同整数值(数据库字段显然是int(或大int微时间))

以及如何显示?容易与JavaScript。

new Date(unix_timestamp); 

这会在用户的时区中产生日期和时间。

+1

不能一致认同。唯一的日期和时间应该被表示为字符串在用户屏幕上的薄层像素上。 – Jerry

+0

我很抱歉...我会澄清所有关心的数据都存储为MySQL日期时间类型 – GDP

+0

此外,不关心显示,这是“简单”。它知道PHP使用date()vs的时候,MySQL默认使用时间戳,与整个网络中各种服务器应用程序中设置的时区一致。 – GDP