経緯
UTCで動いているサーバで、
- UTCで入っている現在時刻をJSTに変換
- 実行日の前日の日付を取得
- 前日データをうんぬんかんぬん
というバッチを日本時間の朝7時に毎日回す想定で、PHPでこんなコードを書いた。
前日日付を8ケタで返すコード?
$y = new DateTime('yesterday');
$y->setTimezone(new DateTimeZone('Asia/Tokyo'));
$yesterday = $y->format('Ymd');
ところが、これで取得した8ケタの日付が前日でなく前々日だったという…。
yesterday
≠ -1 day
だった
var_dumpを張ってみて発覚。new DateTime('yesterday');
の認識が誤っていた。
てっきりちょうど1日前の日時を返してくれるものだと思っていたら…
実験1
$y = new DateTime('yesterday');
var_dump($y);
出力1
object(DateTime)#126 (3) {
["date"]=>
string(26) "2017-10-31 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
$y
には前日の00:00:00が格納されていた。
つまりJSTの7時(UTCの22時)にこのコードを動かすと、$y
には22+24=46時間だけ遡った時刻が格納されてしまう。
そのために、実行した日本時間7時の46時間前、つまり前々日ぶんのデータをうんぬんかんぬんしていたご様子。
「昨日」でなく、「昨日の今」まで取得したいなら、こうでした。
実験2
$y = new DateTime('-1 day');
var_dump($y);
出力2
object(DateTime)#126 (3) {
["date"]=>
string(26) "2017-10-31 04:54:02.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
これでピッタリ24時間前。
まとめ
昨日の日付のみが欲しいのであれば'yesterday'
時刻まで込みで欲しいのであれば'-1 day'
毎日決まった時刻に動くバッチを実装する際、昨日の日付が欲しくなったときは、相対日付は'yesterday'
でなく'-1 day'
を選んだ方が無難そうです。
実は公式ドキュメントにも説明がありました