用于获取 UTC 时区的 Web 和数据库服务器设置 "right"
Web and Database server settings to get UTC timezone "right"
我不知所措地试图做到这一点:我们的服务器分布在十几个时区,Apache 和 MySQL 运行 在全部或部分服务器上,以及MySQL 托管在 Amazon RDS 上。
我想知道 "Best Practices",或者如何配置每个 MySQL 和 PHP 安装,以便当从 PHP 向数据库添加行时,我我确定那里的值实际上是事件发生时的 UTC 时间,而不管事件发生时服务器位于 何处 。在任何给定时区将其呈现给用户不是问题 - 我只想知道日期时间列实际上存储了发生某些事情的实际时刻。
就像现在一样,网络服务器被设置为任何本地时区是由于预定的事件等,我不确定拼图的哪些部分使用哪些设置从哪里得出任何结果已写入数据库。
如果问题看起来不清楚,我深表歉意,在这一点上我不知道我不知道什么,所以得到一个精确的问题甚至具有挑战性。此外,我们所有的日期都在数据库中作为 DateTime 字段,因此无法存储时间戳。
非常简单,始终将 unix time 存储在数据库中(或者如果您希望 microtime 具有微秒精度)。然后,无论您的每个网络服务器的时区如何,如果其中两个同时收到请求,它将是保存在数据库中的相同整数值(数据库字段显然应该是一个 int(或 big int for微时))
以及如何显示?轻松 javascript.
new Date(unix_timestamp);
这会生成用户所在时区的日期和时间。
如果您限制自己使用 MySQL 的 DATE 和 DATETIME 类型,您可以在很大程度上忽略 MySQL 本身的时区问题。您想避免使用 MySQL 的 TIMESTAMP 类型,因为:
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time.
就 reading/writing DATETIME 值而言,您将准确返回输入的内容,这很好。
这给您留下了始终确保将 UTC 值写入数据库的问题。
确保 PHP 使用 UTC 的最佳方法是使用 date_default_timezone_set() 在您的应用程序中明确设置它。这将确保 date('Y-m-d H:i:s')
之类的调用将为您提供 UTC 值。它还将确保 (new \DateTime('now'))->getTimezone()
之类的东西将 return UTC \DateTimeZone 实例。
当然,您应该注意,当您存储从用户那里获取的 date/time 值时,事情会变得更加困难。在这些情况下,您需要以某种方式确定用户所在的时区,并在保留值之前处理到 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');
我不知所措地试图做到这一点:我们的服务器分布在十几个时区,Apache 和 MySQL 运行 在全部或部分服务器上,以及MySQL 托管在 Amazon RDS 上。
我想知道 "Best Practices",或者如何配置每个 MySQL 和 PHP 安装,以便当从 PHP 向数据库添加行时,我我确定那里的值实际上是事件发生时的 UTC 时间,而不管事件发生时服务器位于 何处 。在任何给定时区将其呈现给用户不是问题 - 我只想知道日期时间列实际上存储了发生某些事情的实际时刻。
就像现在一样,网络服务器被设置为任何本地时区是由于预定的事件等,我不确定拼图的哪些部分使用哪些设置从哪里得出任何结果已写入数据库。
如果问题看起来不清楚,我深表歉意,在这一点上我不知道我不知道什么,所以得到一个精确的问题甚至具有挑战性。此外,我们所有的日期都在数据库中作为 DateTime 字段,因此无法存储时间戳。
非常简单,始终将 unix time 存储在数据库中(或者如果您希望 microtime 具有微秒精度)。然后,无论您的每个网络服务器的时区如何,如果其中两个同时收到请求,它将是保存在数据库中的相同整数值(数据库字段显然应该是一个 int(或 big int for微时))
以及如何显示?轻松 javascript.
new Date(unix_timestamp);
这会生成用户所在时区的日期和时间。
如果您限制自己使用 MySQL 的 DATE 和 DATETIME 类型,您可以在很大程度上忽略 MySQL 本身的时区问题。您想避免使用 MySQL 的 TIMESTAMP 类型,因为:
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time.
就 reading/writing DATETIME 值而言,您将准确返回输入的内容,这很好。
这给您留下了始终确保将 UTC 值写入数据库的问题。
确保 PHP 使用 UTC 的最佳方法是使用 date_default_timezone_set() 在您的应用程序中明确设置它。这将确保 date('Y-m-d H:i:s')
之类的调用将为您提供 UTC 值。它还将确保 (new \DateTime('now'))->getTimezone()
之类的东西将 return UTC \DateTimeZone 实例。
当然,您应该注意,当您存储从用户那里获取的 date/time 值时,事情会变得更加困难。在这些情况下,您需要以某种方式确定用户所在的时区,并在保留值之前处理到 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');