【发布时间】:2011-11-06 11:59:38
【问题描述】:
我应该如何处理时区。只为用户存储偏移量是否安全?或者我也应该有区域/位置?当我比较 Wikipedia 和 PHP 中的偏移值时,有些不匹配。我应该相信哪个?
最后我应该如何在 PHP 中使用它。我可以只做一个“时间 - 服务器偏移量 + 用户偏移量”吗?
【问题讨论】:
我应该如何处理时区。只为用户存储偏移量是否安全?或者我也应该有区域/位置?当我比较 Wikipedia 和 PHP 中的偏移值时,有些不匹配。我应该相信哪个?
最后我应该如何在 PHP 中使用它。我可以只做一个“时间 - 服务器偏移量 + 用户偏移量”吗?
【问题讨论】:
如果您关心保留所有数据,则区域和位置很重要。存储日期的最佳方式(在我看来)是存储 UTC 时间戳 + 位置。
对于某些计算,仅偏移量可能就足够了,但如果您有时间戳,并且想知道“+1 天”之类的确切时间,那就不够了。因为这在不同国家有不同的夏令时规则。
因此,如果您想绝对确定您没有“丢失信息”并且将来无法进行基于时间的计算,请存储 UTC 时间戳和 olson id(例如:欧洲/阿姆斯特丹)。
回答你的第二个问题,如果你有这两条信息,你可以很容易地用 DateTime 重构它:
$dt = new DateTime('@' . $timeStamp);
// Now convert it to the users timezone
$dt->setTimeZone(new DateTimeZone('Europe/Berlin'));
// Now you have a 'DateTime' object which you can easily display with the ->format function.
加法
我个人更喜欢将时间戳存储为整数。 TIMESTAMP 类型进行自动转换,我觉得让 PHP 应用程序处理这个更好,这对于我认为您的用例(用户的简单本地化)特别有意义。
使用 DATETIME 也可以,但存储要求远高于仅使用整数。如果您确实更喜欢 DATETIME,请尝试在您的应用程序中将每个值始终存储为 UTC 的规则,因为永远不会有任何混淆,尤其是在您当地时区的 DST 转换和法律更改方面。
如果您只是想在 Web 应用程序上显示基于用户本地时区计算的时间,则偏移量是无用的。大多数国家/地区的抵消额每年变化两次,几乎每年都会有一两个国家/地区发生这种情况。
如果您使用 PHP 很棒的 DateTime 和 DateTimeZone 对象,您只需要该位置。
最后一点建议:
人们倾向于在 PHP 应用程序中混淆日期和时间,并以许多不同的格式(字符串、整数等)发送这些值,并混合 GMT 和 UTC。尝试为自己制定一个规则,永远在函数参数和返回值中发送 DateTime 对象,这样你就可以输入提示,并且永远不会怀疑变量的格式。它将是值得。
【讨论】:
你提到了一个用户。我建议您让用户选择他/她的时区并将其存储在您的数据库中。
这里是如何同步每个会话和用户设置的 PHP (>=5.3) 和 MySQL 时区。当你需要设置和同步时区时,把它放在它运行的地方。
date_default_timezone_set($my_timezone);
$n = new \DateTime();
$h = $n->getOffset()/3600;
$i = 60*($h-floor($h));
$offset = sprintf('%+d:%02d', $h, $i);
$this->db->query("SET time_zone='$offset'");
其中 $my_timezone 是 PHP 时区列表中的一个:http://www.php.net/manual/en/timezones.php
PHP 时区必须转换为 MySQL 的小时和分钟偏移量。这就是第 1-4 行所做的。查询行使用 Code Igniter 框架,您可能不会使用,但查询显示在括号中。
【讨论】:
如果您使用的是 MySQL,您可以使用 (mysql_tzinfo_to_sql) 中的时区信息,它会根据时区自动识别用户时间。您必须创建一个类型的列时间戳,用于存储用户时区信息。
【讨论】: