2013-07-30 76 views
2

我正在連接到以ISO8601格式返回調度信息的JSON事件API。PHP:將ISO8601偏移量轉換爲實際時區

"schedule": [ 
{ 
    "datetime": "2014-06-02T19:30:00-04:00", 
    "speaker": "Keith Moore" 
}, 
{ 
    "datetime": "2014-06-03T19:30:00-04:00", 
    "speaker": "Phyllis Moore" 
] 

當我echo date("c", strtotime($schedule[$j]["datetime"]));我得到2014-06-02T18:30:00-05:00。當然,這是有道理的,因爲date()使用服務器的時區。

如果我將時區傳遞給date()或使用date_default_timezone_set),那麼它應該解決問題。不幸的是,沒有關於什麼時區在ISO8610(只是偏移量)的規範。如果我嘗試從ISO8601日期獲取時區,使用date(),則時區會返回到服務器。

我想要做的是顯示事件本地的日期/時間/時區(在本例中爲東部夏令時)。有沒有辦法做到這一點?

,我想到的一對夫婦的選擇,但也似乎是適當的...

由於我有過API控制,我可以在RFC發送調度信息822格式(星期一,2014年6月2日19:美國東部時間30:00)。這會給我的鉤子,我可以做...

if ($pubDatetimezone == "PST" || $pubDatetimezone == "PDT") date_default_timezone_set("America/Los_Angeles"); 
if ($pubDatetimezone == "MST" || $pubDatetimezone == "MDT") date_default_timezone_set("America/Denver"); 
if ($pubDatetimezone == "CST" || $pubDatetimezone == "CDT") date_default_timezone_set("America/Chicago"); 
if ($pubDatetimezone == "EST" || $pubDatetimezone == "EDT") date_default_timezone_set("America/Montreal"); 

...但ISO8601只是好像更合適的格式。

另一方面,我可以做一些過於複雜的數組,其中我指定每個可能的日期/偏移組合與時區。當然,這似乎是太多的工作。

+1

出於好奇,你考慮過PHP的DateTime類來幫助你解決你的問題嗎? –

+0

我不知道它存在。它可以從偏移量中確定一個時區嗎? – doubleJ

+1

[將UTC時間偏移轉換爲時區或日期]可能的重複(http://stackoverflow.com/questions/11820718/convert-utc-offset-to-timezone-or-date) – vascowhite

回答

3

您應該使用PHP的DateTime。由於ISO8601是一個國際標準,PHP支持它。你需要的代碼如下:

$dt = DateTime::createFromFormat(DateTime::ISO8601, '2014-06-03T19:30:00-04:00'); 

您可以指定第三個參數,您可以使用一個DateTimeZone目的是進一步偏移給定的日期。

例如,如果你想使用北京時間是GMT

$dt = DateTime::createFromFormat(DateTime::ISO8601, '2014-06-03T19:30:00-04:00', new DateTimeZone('Europe/London')); 

而在這之後,所有剩下的就是:

echo $dt->format('d.m.Y, H:i:s'); // format is the same as for date() function. 
+0

但這就是問題所在。我不知道實際的時區是什麼。 -04:00可能是EDT或AST。我確實有位置信息(城市和州),但有多個州包含兩個時區(更不用說所有外國我都不知道了) – doubleJ

+1

datetime對象爲您提供偏移量'($ dt->如果你想要一個偏移量對應的時區,使用類似'echo timezone_name_from_abbr(「」,3600 * $ dt-> getOffset(),0);'應該給你一些有意義的東西 –

+0

' $ dt-> getOffset()'做了我一直在尋找的東西,它在尼日利亞阿布賈的時間表上遇到了問題,我有一個日期/時間爲'2013-11-01T18:00:00 + 01: 00',它輸出的是歐洲/倫敦,我相信問題在於西非時間沒有夏令時,我可以指定一個覆蓋任何古怪的東西 – doubleJ

-1

給予的答案,而好非常有幫助,仍然留下了太多沒有考慮到的例外(輸出錯誤的時區縮寫,即使偏移量相同)。

由於我對API的控制,我只是包含一個時區字段。

"schedule": [ 
{ 
    "datetime": "2013-08-02T18:30:00-05:00", 
    "timezone": "CDT", 
    "speaker": "Happy Caldwell" 
} 
] 

然後,當使用這些數據時,我只是做了一個比較並將服務器設置爲該時區。

if ($timezone == "HAST" || $timezone == "HADT") date_default_timezone_set("Pacific/Honolulu"); 
if ($timezone == "AKST" || $timezone == "AKDT") date_default_timezone_set("America/Juneau"); 
if ($timezone == "PST" || $timezone == "PDT") date_default_timezone_set("America/Los_Angeles"); 
if ($timezone == "MST" || $timezone == "MDT") date_default_timezone_set("America/Boise"); 
// doesn't observe dst 
if ($state == "AZ") date_default_timezone_set("America/Phoenix"); 
if ($timezone == "CST" || $timezone == "CDT") date_default_timezone_set("America/Chicago"); 
if ($timezone == "EST" || $timezone == "EDT") date_default_timezone_set("America/New_York"); 
// doesn't observe dst 
if ($timezone == "PET") date_default_timezone_set("America/Lima"); 
if ($timezone == "AST" || $timezone == "ADT") date_default_timezone_set("America/Puerto_Rico"); 
// doesn't observe dst 
if ($timezone == "GMT") date_default_timezone_set("Europe/London"); 
if ($timezone == "CET" || $timezone == "CEST") date_default_timezone_set("Europe/Amsterdam"); 
// doesn't observe dst 
if ($timezone == "WAT") date_default_timezone_set("Africa/Lagos"); 

現在,我敢肯定有一個更好的方法來做到這一點(可能與DateTime)。隨意評論更好的方法來執行相同的功能。不過,這確實可以做到所需。

當然,這不會幫助只有時區偏移的人。在這些情況下,您可能需要使用其他答案之一,只處理例外情況。

+0

-1,因爲這個答案解決了OP的問題。問題,但沒有回答所問的問題(是的,我知道海報是OP)。如果OP會接受或發佈一個問題答案實際上回答了問題,然後我將刪除-1。 – dotancohen

+0

哎喲...我明白規則。不幸的是,我不認爲有答案。對原始帖子的評論可能會更合適,但是您可以將該代碼發佈在評論中嗎?讓人驚訝。 – doubleJ