gpt4 book ai didi

php - PHP,MySQL和时区

转载 作者:IT老高 更新时间:2023-10-28 23:48:47 26 4
gpt4 key购买 nike

我正在尝试将时区系统集成到我的应用程序中,直到现在为止我一直在努力避免制作时区感知的应用程序-但是现在它是强制性要求,因此别无选择。 TimeZones只是在我头上。我已经在PHP.net和其他站点(包括但不限于SO)上阅读了多个主题。但是我永远也无法掌握。

所以我想知道是否有人可以在这里帮助我:(我想要做的是我应用程序中的一个首选项,允许用户从选择菜单中选择自己的时区,但是该应用程序还应该能够设置/为每个用户相应地选择DST。

请确保这将对仍在努力争取时区的其他人有所帮助,所以即使您必须考虑我是一个完整的小飞象/傻瓜,也请提供尽可能详细的解释。

编辑赏金:

我为这个问题添加了一笔赏金,因为我真的很需要编写PHP/MySQL应用程序时需要一个有关时区的规范性问题(因此,我还添加了MySQL标签)。我已经从很多地方找到了东西,但是最好将它们放在一起。查尔斯的回答很好,但我仍然觉得它缺少一些。这是我想到的一些事情:

  • 如何从PHP DateTime对象
  • 将时间存储在数据库中
  • 应该将它们存储在DATETIME还是TIMESTAMP中?每个都有什么好处或警告?
  • 我们是否需要担心MySQL DATE的时区?
  • 如何使用NOW()插入值。这些是否需要在插入之前或之后以某种方式进行转换?
  • 是否需要设置MySQL使用的时区?如果是这样,怎么办?应该持久执行还是应每个HTTP请求执行?是否必须将其设置为UTC还是其他名称?还是服务器的时间足够?
  • 如何从MySQL检索值并将它们转换为DateTime对象。将其直接放入DateTime::__construct()就足够了吗?还是需要使用DateTime::createFromFormat()
  • 什么时候可以转换成当地时间,为什么。在将它回显给用户之前(例如,与另一个DateTime对象或静态值进行比较),我们是否曾经有过一段时间要对其进行转换?
  • 我们是否曾经需要担心夏令时(DST)?为什么或者为什么不?
  • 如果某人先前已插入数据(例如,使用NOW())而又不必担心时区以确保所有内容保持一致,该怎么办?
  • 您想到别人应该注意
  • 的其他事项

    如果可能,请尝试将其分成逻辑部分,以使将来的用户更容易找到信息。请确保在必要时提供代码示例。

    最佳答案

    此答案已更新,以适应赏金。原始的未编辑答案在该行下方。

    赏金拥有者添加的几乎所有问题都与在时区范围内MySQL和PHP日期时间应如何交互有关。

    MySQL still has pathetic timezone support,这意味着智能必须在PHP端。

  • 如上面的链接中所述,将您的MySQL连接时区设置为UTC。这将导致由MySQL处理的所有日期时间(包括NOW())得到合理处理。
  • 除非您非常明确地要求 DATETIME中的特殊行为,否则
  • Always use TIMESTAMP , never use TIMESTAMP 。这比以前减轻了痛苦。
  • 如果需要,可以将Unix纪元时间存储为整数是可以的,例如,出于遗留目的。时代是UTC。
  • MySQL的首选日期时间格式是使用PHP日期格式字符串Y-m-d H:i:s
  • 创建的
  • 将所有PHP日期时间存储在MySQL中时,将所有PHP日期时间转换为UTC,这很简单,如下所述
  • 从MySQL返回的
  • Datetimes可以安全地传递给PHP DateTime构造函数。请务必同时传递UTC时区!
  • 很快就将PHP DateTime转换为echo的用户本地时区。值得庆幸的是,DateTime与其他DateTime的比较和数学运算将考虑每个DateTime所在的时区。
  • 您仍然需要随PHP一起提供的DST数据库的异想天开。保持您的PHP和OS修补程序为最新!使MySQL保持UTC的幸福状态,以消除一种潜在的DST烦恼。

  • 这解决了大多数问题。

    最后一件事是笨拙的:

    • What should someone do if they have previously inserted data (e.g. using NOW()) without worrying about the time zone to make sure everything stays consistent?


    这真是一件烦人的事。另一个答案指出了MySQL的 CONVERT_TZ ,尽管我个人通过在选择和更新过程中在服务器本地时区和UTC时区之间切换来做到这一点,因为我是这样的顽固派。

    the app should also be able to SET/Choose the DST accordingly itself for each user.



    在现代,您不需要也不应这样做。

    现代版本的PHP具有 DateTimeZone类,其中包括 list named timezones的功能。命名时区允许用户选择其实际位置,并使系统根据该位置自动确定其DST规则。

    您可以将DateTimeZone与 DateTime结合使用,以实现一些简单但功能强大的功能。您可以简单地在UTC by default中存储和使用所有时间戳,并将它们转换为所显示的用户时区。
    // UTC default
    date_default_timezone_set('UTC');
    // Note the lack of time zone specified with this timestamp.
    $nowish = new DateTime('2011-04-23 21:44:00');
    echo $nowish->format('Y-m-d H:i:s'); // 2011-04-23 21:44:00
    // Let's pretend we're on the US west coast.
    // This will be PDT right now, UTC-7
    $la = new DateTimeZone('America/Los_Angeles');
    // Update the DateTime's timezone...
    $nowish->setTimeZone($la);
    // and show the result
    echo $nowish->format('Y-m-d H:i:s'); // 2011-04-23 14:44:00

    通过使用此技术,系统将自动为用户选择正确的DST设置,而无需询问用户当前是否在DST中。

    您可以使用类似的方法来呈现选择菜单。您可以连续地为单个DateTime对象重新分配时区。例如,此代码此刻将列出区域及其当前时间:
    $dt = new DateTime('now', new DateTimeZone('UTC')); 
    foreach(DateTimeZone::listIdentifiers() as $tz) {
    $dt->setTimeZone(new DateTimeZone($tz));
    echo $tz, ': ', $dt->format('Y-m-d H:i:s'), "\n";
    }

    通过使用一些客户端魔术,可以大大简化选择过程。 Javascript具有 spotty but functional Date类,并具有 get the UTC offset in minutes的标准方法。在用户时钟正确的盲目假设下,您可以使用它来帮助缩小可能的时区列表。

    让我们将这种方法与自己进行比较。除了覆盖他们并不真正在乎的用户之外,您还需要在每次操作日期时间时实际执行一次日期数学运算。这不仅是次优的,而且是 bat 鸟粪的疯狂。强制用户在需要DST支持时注明需要麻烦和困惑。

    此外,如果您想为此使用现代化的PHP DateTime和DateTimeZone框架,则需要使用 use deprecated Etc/GMT... timezone strings而不是命名时区。这些区域名称可能会从将来的PHP版本中删除,因此这样做是不明智的。我说的都是经验。

    tl; dr :使用现代工具集,免除日期数学的恐惧。向用户显示名为时区的 列表。 将您的日期存储在UTC的中,它不会受到DST的任何影响。在显示上将日期时间转换为用户选择的命名时区 ,而不是更早。

    根据要求,这是一个可用时区的循环,以分钟为单位显示其GMT偏移量。我在这里选择分钟来演示一个不幸的事实:并非所有的补偿都是一个小时!实际上,有些人在夏令时期间提前了半个小时而不是整整一个小时。以分钟为单位的最终偏移量应与Javascript的Date.getTimezoneOffset相匹配。
    $utc = new DateTimeZone('UTC');
    $dt = new DateTime('now', $utc);
    foreach(DateTimeZone::listIdentifiers() as $tz) {
    $local = new DateTimeZone($tz);
    $dt->setTimeZone($local);
    $offset = $local->getOffset($dt); // Yeah, really.
    echo $tz, ': ',
    $dt->format('Y-m-d H:i:s'),
    ', offset = ',
    ($offset / 60),
    " minutes\n";
    }

    关于php - PHP,MySQL和时区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5768380/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com