Help us understand the problem. What is going on with this article?

DateTimeの計算は参照渡し

More than 5 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とは違い自身を変更せずオブジェクトを返す)を使うことで、簡単に実装できるそうです。

YusukeHigaki
株式会社ニコリーで代表をしております。起業当初は自分でも開発をしていたのですが、最近はCTO以下、自分より遥かに優秀なメンバーにバトンタッチし、もっぱら企画や営業周りを統括しています。自分で書いていた経験もあり、エンジニアという職種に対するリスペクトは絶大です。
http://ticktockblog.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away