【问题标题】:Setting timezone offset in PHP在 PHP 中设置时区偏移
【发布时间】:2016-02-26 02:45:57
【问题描述】:

我正在编写一个 API,它将从传感器检索读数并返回时间和值列表,使用 Javascript 的 `new Date() 进行偏移。(原因见下文) p>

使用$date->sub(DateInterval::createFromDateString($offset . " minutes")),我已经能够使时间加法/减法工作得很好,但返回的时间和日期的偏移量为+00:00(例如2016-02-26T13:32:28+00:00,而不是2016-02-26T13:32:28+11:00 用于澳大利亚)。

这会导致 Pebble 或 AngularJS 之类的东西出现问题,在看到偏移量为 +00:00 后,它们会在我自己的基础上应用自己的偏移量

调用$date->format("c")时如何正确设置偏移量?我应该自己编译日期(例如$date->format("Y-m-d\TH:i:s" . $plusOrMinus . $myoffset->format("h:i")))还是有更好的方法?

编辑:由于平台限制(例如 Pebble 智能手表),我不能或不想使用时区名称,因为在我的手表应用程序中实现时区菜单会破坏 UX 或驱动文件大小如果我向时区表/库添加偏移量

【问题讨论】:

    标签: php datetime timezone


    【解决方案1】:

    我最终解决了这个问题。来自PHP manual 的这条信息告诉了我:

    当 $time 参数是 UNIX 时间戳(例如 @946684800)或指定时区(例如 2010-01-28T15:00:00+02:00)时,$timezone 参数和当前时区将被忽略。

    所以我最终的解决方案是扩展DateTime 类并覆盖__construct() 方法。我修改的类如下:

    <?php
    
      class timezone extends DateTime {
    
        // Override our __construct method
        function __construct($date = "now", $offset = null) {
          // If we've not specified an offset
          if(is_null($offset)) {
              // Assume UTC
              $offsetFormat = "+00:00";
              $offset = 0;
          // Otherwise..
          } else {
            // Create a new DateTime, and get the difference between that, and another new DateTime that has $offset minutes subtracted from it. Format the results as something like +11:00 or -03:00
            $offsetFormat = (new DateTime($date, new DateTimeZone("UTC")))->diff((new DateTime($date, new DateTimeZone("UTC")))->sub(DateInterval::createFromDateString($offset . " minutes")))->format("%R%H:%I");
          }
    
          // Next, we get the offset from our $date. If this offset (divided by 60, as we're working in minutes, not in seconds) does NOT equal our offset
          if((new DateTime($date))->getOffset() / 60 !== $offset) {
            // Overwrite $date, and set it to a new DateTime with $offset minutes subtracted from it
            $date = (new DateTime($date, new DateTimeZone("UTC")))->sub(DateInterval::createFromDateString($offset . " minutes"));
          // If $date's offset equals $offset
          } else {
            // An offset has already been applied (we know this because all our pre-offset dates will be in UTC), and we don't need to do it again
            $date = (new DateTime($date));
          }
    
          // Finally, hand this back to the original DateTime class. This format works out to be something like: 2016-03-10T23:16:37+11:00
          parent::__construct($date->format("Y-m-d\TH:i:s") . $offsetFormat, null);
        }
    
      }
    
    
      echo (new timezone())->format("c") . "<br />"; // Will output something like 2016-03-10T12:17:44+00:00
      echo (new timezone(null, -660))->format("c") . "<br />"; // Will output something like 2016-03-10T23:17:44+11:00
      echo (new timezone("midnight", -660))->format("c") . "<br />"; // Will output 2016-03-10T11:00:00+11:00
      echo (new timezone("midnight"))->format("c") . "<br />"; // Will output 2016-03-10T00:00:00+00:00
      echo (new timezone("2016-01-01T00:00+00:00", -660))->format("c") . "<br />"; // Will output 2016-01-01T11:00:00+11:00
      echo (new timezone("2016-01-01T00:00+11:00", -660))->format("c") . "<br />"; // Will output 2016-01-01T11:00:00+11:00. Note that the offset isn't applied twice!
    
     ?>
    

    编辑:现在这是我开源的一个库。 Check it out over on GitHub

    【讨论】:

      【解决方案2】:

      这是?

      $date = new DateTime('now', new DateTimeZone('Australia/Adelaide'));
      var_dump($date);
      var_dump($date->format('c'));
      

      输出是

      object(DateTime)[2]
        public 'date' => string '2016-02-26 13:35:48.000000' (length=26)
        public 'timezone_type' => int 3
        public 'timezone' => string 'Australia/Adelaide' (length=18)
      string '2016-02-26T13:35:48+10:30' (length=25)
      

      【讨论】:

      • 由于平台限制(例如 Pebble 智能手表,要求时区破坏 UX),我正在从 Javascript 中检索偏移量,因此偏移量将以分钟为单位(例如墨尔本比 UTC 早 660 分钟) )。编辑:有这个选项:stackoverflow.com/questions/7276304/… 但显然它不能很好地处理夏令时
      猜你喜欢
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      相关资源
      最近更新 更多