2017-09-29 61 views
1

我已經從一個時區轉換DateTime對象到另一個,並且處理讀交易每一個問題通常是相同的:DateTime對象和顯示的日期/時間在備用時區

$date->setTimezone($newTimezone); 
$date->format($format); 
$date->setTimezone($oldTimezone); 

作爲間歇過程,必要時循環前兩項,根據需要更改date_default_timezone_set

我所擁有的是一個顯示多個時區的約會時間窗口小部件,我發現我必須要麼:

  • 創建多個DateTime對象,並改變他們的每一個當到期日到達窗口小部件,或
  • 使用一個DateTime對象,但遍歷所需的每個時區,主動將其更改爲每個時區,顯示它,沖洗並重復。

什麼努力做的是有一個DateTime對象設置爲用戶的時區,從來沒有改變,但顯示它相關的其它時區。我知道這是不支持的,但我怎樣才能最好地實現這一目標?

我不喜歡管理多個DateTime對象,它根本不需要。我寧願是一個方法,如:

DateTime::formatForTimezone($format, $timezone) 

DateTime::inTimezone($timezone) 

,我可以再使用:

$date->inTimezone($timezone)->format($format) 

$date的時區將保持不變。我可以迭代所需的時區,原始對象將被保留。我已經寫了一個函數來實現這一點,但我忘記了所有對象都是通過引用傳遞的,所以當我的函數返回對象時區已經改變了我需要恢復的東西,所以函數產生了更多的工作(所以我報廢了它)。但它看起來像這樣:

function DateInTimezone(DateTime $date, DateTimeZone $tz, $format){ 
    $backup = $date->getTimezone(); 
    $date->setTimezone($tz); 
    $output = $date->format($format); 
    $date->setTimezone($backup); 
    return $output; 
} 

我剛纔做了一個class extends。基本上同樣的事情,只是剪掉一個變量。

class DateTimeForTimezone extends DateTime { 
    public function formatForTimezone($format, DateTimeZone $tz){ 
     $backup = $this->getTimezone(); 
     $this->setTimezone($tz); 
     $output = $this->format($format); 
     $this->setTimezone($backup); 
     return $output; 
    } 
} 

我是第一個承認,我沒有完全理解OOP,任何指針將是有益的

例如,這不就是我後:

CODE :

echo '<pre>'; 

function p($arg){ 
    echo "$arg\n"; 
} 
class DateTimeForTimezone extends DateTime { 
    public function formatForTimezone($format, DateTimeZone $tz){ 
     $backup = $this->getTimezone(); 
     $this->setTimezone($tz); 
     $output = $this->format($format); 
     $this->setTimezone($backup); 
     return $output; 
    } 
} 
$f = "Y-m-d H:i:s A T O e"; 
$date = new DateTimeForTimezone('now',new DateTimeZone('UTC')); 

$tzAUS = new DateTimeZone("Australia/Sydney"); 
$tzBKK = new DateTimeZone("Asia/Bangkok"); 
$tzLOS = new DateTimeZone("America/Los_Angeles"); 

// output ending with '*' should all be UTC 
p($date->format($f."*")); 
p($date->formatForTimezone($f,$tzLOS)); 
p($date->format($f."*")); 
p($date->formatForTimezone($f,$tzAUS)); 
p($date->format($f."*")); 
p($date->formatForTimezone($f,$tzBKK)); 
p($date->format($f."*")); 

OUTPUT:

2017-09-29 23:37:20 PM UTC +0000 UTC* 
2017-09-29 16:37:20 PM PDT -0700 America/Los_Angeles 
2017-09-29 23:37:20 PM UTC +0000 UTC* 
2017-09-30 09:37:20 AM AEST +1000 Australia/Sydney 
2017-09-29 23:37:20 PM UTC +0000 UTC* 
2017-09-30 06:37:20 AM +07 +0700 Asia/Bangkok 
2017-09-29 23:37:20 PM UTC +0000 UTC* 

我已經實現了我的目標,但技術上的時區改變,它只是恢復回來。

我只是看着這個錯誤?有沒有更好的方式來實現我所追求的目標?

回答

1

你正確地做到了。區域不僅僅是顯示,它是時間狀態不可分割的一部分。您無法使用時間值,如「2017-05-13T21:54:00」,但不知道其區域。忘記計算,忘記比較,直到你知道該區域。並且不要一分鐘認爲改變時區是微不足道的。這是notoriously complicated。所以,繼續保持你的狀態。

如果你想這個循環沒有管理對象,只是做:

$date = new DateTime('2017-05-13T21:54:00', new DateTimeZone('America/New_York')); 
$zones = [ 
    new DateTimeZone('Antarctica/Casey'), 
    new DateTimeZone('Europe/Helsinki'), 
]; 
foreach ($zones as $zone) { 
    echo (clone $date)->setTimezone($zone)->format('c') . PHP_EOL; 
} 

See this live on 3v4l.org.

+1

掛...首先第一件事情,我喜歡用什麼時間做,我喜歡這個鏈接(書籤)。它讓我想起了一個湯姆斯科特的視頻(https://www.youtube.com/watch?v=-5wpm-gesOY),他在那裏談論他在某個時間點,時區,夏時制,某種程度上提出的應用程序日曆和閏秒。我知道的一切除了「閏秒塗片」!好的谷歌! – Madivad

+1

HANG ON#2!現在,我其實已經在昨天讀過關於克隆的內容,但是我沒有想到將它應用於主體,我試圖在功能中使用它,並決定暫時離開它。沒有意識到,我跳過了我一直在尋找的東西!處理數據克隆和更改時區正是我想要的,並且全部在一行上!很好,謝謝@ bishop。 – Madivad

+0

提出的唯一問題是'clone'的開銷。這是一個問題時間還是內存方面(顯然會有一些內存開銷),我應該改變時區並改回來嗎?我認爲這將是其中一個「6個,另一個是另一個的6個」,但克隆看起來很完美(是的,循環陣列是要走的路,我的例子我剛剛發佈了一個內襯雖然我正在測試,但感謝內存提示) – Madivad

相關問題