在PHP中设置时区偏移

在PHP中设置时区偏移,php,datetime,timezone,Php,Datetime,Timezone,我正在编写一个API,它将检索传感器的读数,并返回一个时间和值列表,使用Javascript的“new Date()进行偏移。(原因见下文) 我已经能够使用$date->sub(DateInterval::createFromDateString($offset.“minutes”)使时间加法/减法工作得很好,但是返回的时间和日期的偏移量为+00:00(例如2016-02-26T13:32:28+00:00而不是2016-02-26T13:32:28+11:00(澳大利亚) 这会导致诸如Pebb

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

我已经能够使用
$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 smartwatch),我不能或不想使用时区名称,因为在我的手表应用程序中实现时区菜单会破坏用户体验,或者如果我向时区表/库添加偏移量,会导致文件大小变大。

是这样吗?

$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)

最后我把它整理好了。这条消息给了我一个通风报信:

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

因此,我最终的解决方案是扩展
DateTime
类并重写
\u 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!

 ?>

由于平台限制(例如Pebble smartwatch,请求时区会中断UX),我正在从Javascript检索偏移量,因此偏移量将以分钟为单位(例如,墨尔本比UTC早660分钟)。编辑:有这个选项:但显然它不能很好地处理夏令时