Edited at

DateTimeの計算は参照渡し

More than 3 years have passed since last update.

知らなかった・・のでメモ。

ある時間から5分前の時刻を取得したい。そんなとき

$date = new \DateTime('2015-02-15');

$subDate = $date->sub(new \DateInterval('PT5M'));
var_dump($subDate)

とやればいいのね、と思っていたが、じつは$date->subで新しいDateTimeオブジェクトが返るわけではなく、$dateオブジェクト自体が変更され、その参照が返るみたい(参照渡し)。

参照渡しされてますね。

[実行プログラム]

$date = new \DateTime('2015-02-10');

$subDate = $date->add(new \DateInterval('PT5M'));
var_dump($subDate);
var_dump($date);

[結果]

object(DateTime)[1]

public 'date' => string '2015-02-09 23:55:00.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Asia/Tokyo' (length=10)
object(DateTime)[1]
public 'date' => string '2015-02-09 23:55:00.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Asia/Tokyo' (length=10)```

ということで下記のようにすればいいです。

$date = new \DateTime('2015-02-10');

$cloneDate = clone $date;
$cloneDate->sub(new \DateInterval('PT5M'));
var_dump($cloneDate);
var_dump($date);

object(DateTime)[2]

public 'date' => string '2015-02-09 23:55:00.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Asia/Tokyo' (length=10)
object(DateTime)[1]
public 'date' => string '2015-02-10 00:00:00.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Asia/Tokyo' (length=10)

[追記]

PHP5.5以上であればDateTimeImmutable(DateTimeとは違い自身を変更せずオブジェクトを返す)を使うことで、簡単に実装できるそうです。