DateTime::getTimestamp()すると日付が変わる件


<?php
    $date = new DateTime('2014/01/01 00:00:00', new DateTimeZone('Asia/Tokyo'));
    $date->modify('first day of -1 second');

    var_dump($date->format('Y-m-d H:i:s')); // 2013-12-31 23:59:59
    var_dump($date->getTimestamp()); // 1385909999 → 2013-12-01 23:59:59
    var_dump($date->format('Y-m-d H:i:s')); // 2013-12-01 23:59:59

何故か日付が変わっています。
なんだこれ。

更に深刻なことにはDateTimeImmutableでも発生します。

<?php
    $date = new DateTimeImmutable('2014/01/01 00:00:00');
    $date2 = $date->modify('first day of -1 second');
    var_dump($date2->format('Y-m-d H:i:s')); // 2013-12-31 23:59:59
    var_dump($date2->getTimestamp()); // 1385909999 → 2013-12-01 23:59:59
    var_dump($date2->format('Y-m-d H:i:s')); // 2013-12-01 23:59:59

あかんこれ。

ポイントは'first day of -1 second'と複数の変更を一気に指定するところです。

    $date->modify('first day of');
    $date->modify('-1 second');

と分けて記述すると何故か発生しません。

また'-1 minute''-1 hour'では発生しますが'-1 day''+1 second'は正常に計算されます。
'first Saturday of next month -1 second''Monday next week -1 second'などでも発生しません。
'first day''last day'と一日以下のマイナス計算が入っているとバグる模様。

カレンダーを作ったときに見つけたのですが、意味がわからなかったので放置していたところ、先日バグレポートが上がっていました。
せっかくだから報告でもしてみればよかったかな。

このバグは、PHP5.6RC2の時点ではまだ修正されていません。
DateTime関連は何気にバグやバグだかなんだかわからない挙動があったりするので、使うときは気をつけないといけませんね。