2013-09-24 115 views
1

結束1小時後我已經定義將該代碼作爲這樣(簡化版本爲清楚起見):PHP時間()和DST問題的端 - DST

$fifteenMinsLater = strtotime('+900 second', time()); 
$now = time(); 
if ($now > $fifteenMinsLater) { 
    mtrace("This should NEVER happen"); 
} 
else { 
    mtrace("This should always be the case"); 
} 

在2013年11月3日上午02點00分DST結束America/New_York並且時鐘將一小時恢復至凌晨1:00。

當我在DST結束後(即凌晨2點之後變成凌晨1點)在上午11/03/03以及上午1點到凌晨2點之間運行上述代碼時,行:

This should NEVER happen 

被打印。但是,在DST轉換之前或新的2:00 AM之後的任何時間都可以。

這導致了一個主要的錯誤,導致用戶試圖訪問使用上述代碼在DST轉換後的一個小時內悲慘失敗的函數。

PHP 5.2.11。

任何想法?

+1

你確定你沒有過於簡單? 'strtotime'&'time'返回unix時間戳,只要知道不是DST知道/不會意外倒計數3600秒。你是比較那些時間戳的表示,而不是原始整數時間戳本身? AFAIK,只有閏秒會影響unix時間戳。 – Wrikken

+0

現在和現在的$ 15MinsLater的回聲將解決這個問題很長的路要走。 –

+0

網站http://3v4l.org非常適合測試不同的PHP版本。只有版本[5.0.0至5.0.2](http://3v4l.org/C1UhE#v500)返回無效比較。 –

回答

0

strtotime()和PHP中的其他日期函數不考慮時區。 DateTime()作用:

$fifteenMinsLater = new DateTime(); 
$fifteenMinsLater->modify('+15 minutes'); 
$now = new DateTime(); 

if ($now > $fifteenMinsLater) { 
    mtrace("This should NEVER happen"); 
} 
else { 
    mtrace("This should always be the case"); 
} 

下面是如何做到這一點在PHP 5.5:

$now = new DateTimeImmutable(); 
$fifteenMinsLater = $now->modify('+15 minutes'); 

if ($now > $fifteenMinsLater) { 
    mtrace("This should NEVER happen"); 
} 
else { 
    mtrace("This should always be the case"); 
} 
+0

是的,他們確實沒有考慮時區,但這是整個觀點。他們使用UTC unix時間。因此,將15分鐘添加到同一個time()函數應該可以作爲派生時間變量($ now和$ fifteenMinLater),但是是int unix時間戳。我會給你的答案投一票(如果我有足夠的代表),因爲在PHP 5.3.6中使用你的第一個代碼產生了正確的結果。然而,在PHP 5.2.17上使用它顯示了同樣的問題,這導致我相信PHP 5.2.x中存在繼承錯誤。非常感謝! – user2719933

+0

這可能是[bug](https://bugs.php.net/bug.php?id=51051) – user2719933