【问题标题】:Working with timezone in PHP & MySQL在 PHP 和 MySQL 中使用时区
【发布时间】:2011-11-06 11:59:38
【问题描述】:

我应该如何处理时区。只为用户存储偏移量是否安全?或者我也应该有区域/位置?当我比较 Wikipedia 和 PHP 中的偏移值时,有些不匹配。我应该相信哪个?

最后我应该如何在 PHP 中使用它。我可以只做一个“时间 - 服务器偏移量 + 用户偏移量”吗?

【问题讨论】:

    标签: php mysql timezone


    【解决方案1】:

    如果您关心保留所有数据,则区域和位置很重要。存储日期的最佳方式(在我看来)是存储 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 对象,这样你就可以输入提示,并且永远不会怀疑变量的格式。它将是值得。

    【讨论】:

    • 所以我只需要区域/位置而不是偏移量?你会建议我把它和用户放在同一个表中还是放在另一个表中。我应该在 MySQL 中使用时间戳而不是日期等其他格式吗?
    • 我添加了一大堆段落来回答这个问题;我应该把它变成一篇博文^_^
    • 最后两个问题。我可以使用 time() 和 NOW() 函数吗?并且服务器时间会和他们的时间同步吗?
    • 是的,如果您将所有内容存储为 INT,请使用 PHP 的 time()。 NOW() 将是 DATETIME 字段的本地时间,因此请避免
    • 您还需要记录 DST 是否处于活动状态,尤其是当您在“回退”时间处理时间时。 10 月最后一个星期日的凌晨 2 点变为凌晨 1 点。所以,2017-10-29 02:00:00 Europe/London => 2017-10-29 01:00:00 Europe/London 如果没有 DST,时间就很模糊。所以,2017-10-29 02:00:00 Europe/London BST => 2017-10-29 01:00:00 Europe/London GMT 这真的很糟糕。但事实就是如此。
    【解决方案2】:

    您可以使用填充timezonesdropdown 菜单将数据库中的时区保存为字符串

    当用户登录时,将时区保存在 $_SESSION['timezone'] 变量中,并在脚本中设置时区,如下所示:

    date_default_timezone_set($_SESSION['timezone']);
    

    【讨论】:

    • 我明白了。所以当我从数据库中得到一个日期(或时间戳?)时,我只需要输入那个值,偏移量就会自动处理?
    【解决方案3】:

    你提到了一个用户。我建议您让用户选择他/她的时区并将其存储在您的数据库中。

    这里是如何同步每个会话和用户设置的 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 框架,您可能不会使用,但查询显示在括号中。

    【讨论】:

      【解决方案4】:

      如果您使用的是 MySQL,您可以使用 (mysql_tzinfo_to_sql) 中的时区信息,它会根据时区自动识别用户时间。您必须创建一个类型的列时间戳,用于存储用户时区信息。

      【讨论】:

      • “存储用户时区信息的时间戳类型的列”是什么意思。
      • 他将有一个字段,其中包含输入/删除/更新数据等的时间......它将是时间戳类型,它会根据时区而有所不同。
      猜你喜欢
      • 2012-07-09
      • 2011-08-11
      • 2011-06-27
      • 2016-03-29
      • 2016-10-17
      • 2011-06-02
      • 2015-04-16
      相关资源
      最近更新 更多