【问题标题】:php: setting a timezone by UTC offsetphp:通过UTC偏移设置时区
【发布时间】:2011-11-08 17:32:38
【问题描述】:

使用 javascript 我知道我的用户时区是 UTC +3。

现在我想用这些知识创建 DateTime 对象:

$usersNow = new DateTime('now', new DateTimeZone("+3"));

我收到了回复:

'Unknown or bad timezone (+2)'

我做错了什么?我该如何解决?

【问题讨论】:

    标签: php datetime timezone


    【解决方案1】:

    这个怎么样...

    $original = new DateTime("now", new DateTimeZone('UTC'));
    $timezoneName = timezone_name_from_abbr("", 3*3600, false);
    $modified = $original->setTimezone(new DateTimezone($timezoneName));
    

    【讨论】:

    • +1 只是为了让另一个 +3^^(开玩笑,你的答案是正确的)。
    • 像魅力一样工作!谢谢你。
    • 这是错误,如果 PHP 处理夏令时。
    • 函数 timezone_name_from_abbr 在调用 +11 偏移时返回 false:timezone_name_from_abbr("", 11*3600, false);
    • 这在通过里约热内卢 (-2*3600) 时损坏了我的生产机器,我得到了Uncaught Exception: DateTimeZone::__construct(): Unknown or bad timezone。我将在下面的答案中粘贴我的修复。
    【解决方案2】:

    你说:

    使用 javascript 我知道我的用户时区是 UTC +3。

    你可能会这样运行:

    var offset = new Date().getTimezoneOffset();
    

    这将返回与 UTC 的 当前 偏移量(以分钟为单位),正值落在 UTC 以西。它确实返回时区!

    时区不是偏移量。时区一个偏移量。它可以有多个不同的偏移量。通常有两种偏移,一种用于标准时间,一种用于夏令时。单个数值不能单独代表这一点。

    • 时区示例:"America/New_York"
      • 对应的标准偏移量:UTC-5
      • 对应的日光偏移:UTC-4

    除了两个偏移量之外,该时区还包含在两个偏移量之间转换的日期和时间,以便您知道它们何时适用。还有关于偏移量和转换如何随时间变化的历史记录。

    另请参阅the timezone tag wiki 中的“时区!= 偏移量”。

    在您的示例中,您可能从 javascript 收到了 -180 的值,表示 当前 UTC+3 的偏移量。但这只是那个特定时间点的偏移量!如果您关注minaz's answer,您将获得一个假设 UTC+3始终是正确偏移的时区。如果实时时区类似于"Africa/Nairobi",它除了UTC+3 之外从未使用过任何东西,这将起作用。但据您所知,您的用户可能在 "Europe/Istanbul",它在夏季使用 UTC+3,在冬季使用 UTC+2。

    【讨论】:

    • 这个答案值得更多的支持。非常详细地解释了@shealtiel 面临的挑战。
    【解决方案3】:

    现代答案:

    $usersNow = new DateTime('now', new DateTimeZone('+0300'));
    

    文档:

    http://php.net/manual/en/datetimezone.construct.php

    【讨论】:

      【解决方案4】:

      自 PHP 5.5.10 起,DateTimeZone 接受类似 "+3" 的偏移量:

      https://3v4l.org/NUGSv

      【讨论】:

        【解决方案5】:

        据我从 DateTimeZone 上的文档得知,您需要传递一个有效的时区,这里是 valid 的时区。检查others,那里可能会对您有所帮助。

        【讨论】:

          【解决方案6】:

          你试过了吗

          http://php.net/manual/en/function.strtotime.php

           <?php
              echo strtotime("now"), "\n";
              echo strtotime("10 September 2000"), "\n";
               echo strtotime("+5 hours");
              echo strtotime("+1 day"), "\n";
              echo strtotime("+1 week"), "\n";
              echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
              echo strtotime("next Thursday"), "\n";
              echo strtotime("last Monday"), "\n";
              ?>
          

          【讨论】:

          • 这可以工作。我真的不需要时区名称,只是为了计算正确的时间。所以“+3 小时”就可以了
          【解决方案7】:

          对于遇到此问题的任何人,我都面临同样的问题,所以最后我扩展了 DateTime 类并覆盖了 __construct() 方法以接受偏移量(以分钟为单位)而不是时区。

          从那里,我的自定义 __construct() 计算出偏移量以小时和分钟为单位(例如 -660 = +11:00),然后使用 parent::__construct() 传递我的日期,自定义格式包括我的偏移量,返回到原来的 DateTime。

          因为我总是在我的应用程序中处理 UTC 时间,所以我的班级还通过减去偏移量来修改 UTC 时间,因此通过午夜 UTC 和 -660 的偏移量将显示上午 11 点

          我的解决方案在这里详述:https://stackoverflow.com/a/35916440/2301484

          【讨论】:

            【解决方案8】:

            这比马修的回答更进一步,将日期的时区更改为任何整数偏移量。

            public static function applyHourOffset(DateTime $dateTime, int $hourOffset):DateTime
            {
                $dateWithTimezone = clone $dateTime;
            
                $sign = $hourOffset < 0 ? '-' : '+';
                $timezone = new DateTimeZone($sign . abs($hourOffset));
                $dateWithTimezone->setTimezone($timezone);
            
                return $dateWithTimezone;
            }
            

            注意:由于接受的答案,我在生产中遇到了问题。

            【讨论】:

              【解决方案9】:

              DateTimeZone 需要一个时区而不是一个节日

              【讨论】:

              • 我如何设置只知道 utc 偏移量的时区?
              • @shealtiel 你不能
              【解决方案10】:

              感谢 Joey Rivera 的链接,我被引导到一个解决方案。就像其他人在这里所说的那样,时区不是您需要有效时区的偏移量。

              这是我自己用的

              $singapore_time = new DateTime("now", new DateTimeZone('Asia/Singapore'));
              
              
              var_dump( $singapore_time );
              

              我自己发现使用 YYYY-MM-DD HH:MM 格式更方便。例子。

              $original = new DateTime("2017-05-29 13:14", new DateTimeZone('Asia/Singapore'));
              

              【讨论】:

                猜你喜欢
                • 2010-11-19
                • 1970-01-01
                • 2018-03-01
                • 2020-03-13
                • 2011-12-25
                • 2016-08-24
                • 2018-02-12
                • 1970-01-01
                • 2014-02-04
                相关资源
                最近更新 更多