2016-09-21 27 views
4

たちは二番目を追加または減算する場合は、このコードを考えてみましょう:このタイムスタンプはちょうどDST(夏時間/サマータイム)内にあるようstrtotime()にバグがありますか?

date_default_timezone_set("Europe/Amsterdam"); 

$time = 1477789199; 
echo $time . ' - ' . date('r', $time) . "\n"; 
// 1477789199 - Sun, 30 Oct 2016 02:59:59 +0200 

をこれは、正しいです。

しかし、今のは、タイムスタンプの整数に1秒を追加してみましょう、と終了 DST:

$new = $time + 1; 
echo $new . ' - ' . date('r', $new); 
// 1477789200 - Sun, 30 Oct 2016 02:00:00 +0100 

万歳! PHPはもう1秒後にはDSTがなく、適切な時間文字列を表示します。

しかし、どのような場合には、我々は、タイムスタンプの整数に秒を追加していないが、我々は二その1を追加するためにstrtotime()を使用:

$new = strtotime('+1 second', $time); 
echo $new . ' - ' . date('r', $new); 
// 1477792800 - Sun, 30 Oct 2016 03:00:00 +0100 

む〜!私たちはちょうど1秒ではなく1時間以上先行しました。 1秒、1時間、1日、または1年を追加しても、1時間余分に追加すると問題はありません。複数年を追加しても毎年DSTに入り、DSTを終了するため1時間余分になりますが、追加年数に関係なく1時間余分になります

しかし、一度は出口 10月のDSTと1秒を引いて、すべてがうまくいく...

しかし、もう一度。私たちが3月に入っていて、DSTに入ったばかりで、1秒を減算すると、まったく同じように観測されます。


待ち、何ですか?そう ... ?私に

echo strtotime('+ 1 second - 1 second', 1477789199); // echoes 1477792799 

おっ


これはバグのように聞こえます。それとも、これは「設計」ですか?誰かがこれがどこかに書かれているのか、それとも報告する必要があるのか​​を知っていますか?テスト中

+0

投稿前にPHPバグプールをチェックした場合、2012年に同様の問題がフォローアップなしで報告されていることがわかりました:https://bugs.php.net/bug.php?id=62185 –

+1

[doc]( http://php.net/manual/en/function.strtotime.php): 'この関数を数学的演算に使用することはお勧めできません。 PHP 5.3以降ではDateTime :: add()とDateTime :: sub()、PHP 5.2ではDateTime :: modify()を使用する方がよいでしょう。 ' –

+0

https://bugs.php.net/bug.php?id=73138 –

答えて

1

行動は「十分に文書化」されて....:

(期待通りにも、あなたの期待される結果を提示)を参照してくださいhttps://bugs.php.net/bug.php?id=30532と(現在の動作が正しいことを主張する)関連テストファイルhttps://github.com/php/php-src/blob/master/ext/date/tests/bug30532.phpt

<?php date_default_timezone_set("America/New_York"); 

echo date('Y-m-d H:i:s T', strtotime('2004-10-31 EDT +1 hour'))."\n"; 
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 EDT +2 hours'))."\n"; 
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 EDT +3 hours'))."\n"; 
/* 2004-10-31 01:00:00 EDT 
    2004-10-31 01:00:00 EST 
    2004-10-31 02:00:00 EST */ 

echo date('Y-m-d H:i:s T', strtotime('2004-10-31 +1 hour'))."\n"; 
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 +2 hours'))."\n"; 
echo date('Y-m-d H:i:s T', strtotime('2004-10-31 +3 hours'))."\n"; 
/* 2004-10-31 01:00:00 EDT 
    2004-10-31 02:00:00 EST 
    2004-10-31 03:00:00 EST */ 

前者の場合はタイムゾーン(ここでは:EDT)ことが注意されていない後者の場合、文字列に直接渡されます。

一般的に、strtotimeは、タイムスタンプ(すなわち、2004-10-31 - またはあなたの特定のケースでは、渡されたタイムスタンプ)をとり、個々のパラメータを持つ表現に変換して、DST(つまり個々の時間、分、秒、年など)、操作はそれに適用され、タイムスタンプに戻されます。特に

echo date('r', strtotime('+ 0 second', 1477789199)); 
#> Sun, 30 Oct 2016 02:59:59 +0100 

strtotime()離れ変換後のタイムゾーンをスロー、すなわち

Sun, 30 Oct 2016 02:59:59 

を取り、その後、あなたのタイムゾーンの場所(すなわち、Europe/Amsterdam)に主に適用タイムゾーンを適用するだけで、CET(プライマリー!)で終わる - CESTすることも可能であるが、唯一の2番目の選択肢。

ここで、上記のテストを振り返って、明示的に元のタイムゾーンを指定してください。

あなたはそれはあなたがそれを必要とする方法振る舞うしたい場合はこのように、:実際には

echo date('r', strtotime('CEST', 1477789199)); 
#> Sun, 30 Oct 2016 02:59:59 +0200 
echo date('r', strtotime('CEST + 1 second', 1477789199)); 
#> Sun, 30 Oct 2016 02:00:00 +0100 

CESTが一致していない場合、それは常にCETにフォールバックされますよう、'CEST 'を付加すると、(すべての時間の罰金になりますCET - >CESTへのオーバーラップはありません)。

関連する問題