6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

new DateTime('yesterday')とnew DateTime('-1 day')の違い

Last updated at Posted at 2017-11-01

経緯

UTCで動いているサーバで、

  1. UTCで入っている現在時刻をJSTに変換
  2. 実行日の前日の日付を取得
  3. 前日データをうんぬんかんぬん

というバッチを日本時間の朝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'を選んだ方が無難そうです。

実は公式ドキュメントにも説明がありました

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?