2016-02-26 153 views
0

我正在編寫一個API,它將從傳感器中檢索讀數並返回時間和值列表,偏移量使用Javascript的new Date()。(見下文的原因)在PHP中設置時區偏移量

我已經能夠獲取時間加法/減法的工作做得不夠好,使用$date->sub(DateInterval::createFromDateString($offset . " minutes")),但返回的時間和日期的偏移量+00:(而不是00如2016-02-26T13:32:28+00:00澳大利亞2016-02-26T13:32:28+11:00)。

這會導致問題的東西,如卵石,或AngularJS,適用於我自己的頂自己的偏移,看到偏移後+00:00

我怎樣才能正確地設置一個呼叫時偏移$date->format("c")?我應該自己編譯日期(例如$date->format("Y-m-d\TH:i:s" . $plusOrMinus . $myoffset->format("h:i")))還是有更好的方法來做到這一點?

編輯:由於平臺限制(例如Pebble smartwatch),我不能或不想使用時區名稱,因爲在我的手錶應用程序中實現時區菜單會破壞UX或驅動文件大小如果我添加一個偏移到時區表/庫

回答

0

我得到這個排序在最後。從PHP manual信息的該位放倒我送行:

在$時區參數和當前時區被忽略時,$時間參數要麼是一個UNIX時間戳(如@ 946684800),或者指定一個時區(如2010- 01-28T15:00:00 + 02:00)。

所以我最終的解決方案是擴展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

0

是這樣嗎?

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

由於平臺限制(例如Pebble smartwatch,要求時區打破UX),我正在從Javascript檢索偏移量,所以偏移量將在幾分鐘內(例如,墨爾本比UTC早660分鐘)。編輯:有這個選項:http://stackoverflow.com/questions/7276304/php-setting-a-timezone-by-utc-offset但顯然它不處理夏時制很好 – Grayda