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

DateTimeクラスとDateTimeImmutableクラスの違いを理解する

More than 1 year has passed since last update.

概要

自分はミュータブルとイミュータブルの違いも分かっていませんでした。
そんな私がDateTimeクラスでハマったことがあったので、これを機会に理解していきます。

特徴

PHP: DateTime - Manual

DateTimeクラスはミュータブルらしいです。

ミュータブルとは
オブジェクトで、作成後も状態を変えることができる。

PHP: DateTimeImmutable - Manual

DateTimeImmutableクラスはイミュータブルらしいです。

イミュータブル
オブジェクトで、作成後は状態を変えることができない。

ふむふむ…。
イミュータブル - Wikipediaによると、ミュータブルとイミュータブルの違いは、オブジェクト作成後にその状態を変えられるかどうかが違いのようです。
これがどのように影響していくるか、次の章で確認してきます。

動作検証

まずは特定の日付でそれぞれのオブジェクトを作成し、14日前の日付に変更します。

$date = new DateTime('2018-04-25');
echo 'DateTime : ';
echo $date->modify('-14 day')->format('Y-m-d H:i:s') . PHP_EOL;

$dateImmu = new DateTimeImmutable('2018-04-25');
echo 'DateTimeImmutable : ';
echo $dateImmu->modify('-14 day')->format('Y-m-d H:i:s') . PHP_EOL;
実行結果
DateTime : 2018-04-11 00:00:00
DateTimeImmutable : 2018-04-11 00:00:00

このときはどちらも同じ結果となります。
これだけの処理ならミュータブルなDateTimeクラスでも不都合はありません。
では、特定の日付を起点に、14日前の日付と30日前の日付を生成してみましょう。

$date = new DateTime('2018-04-25');
echo 'DateTime : ';
echo $date->modify('-14 day')->format('Y-m-d H:i:s') . PHP_EOL;
echo $date->modify('-30 day')->format('Y-m-d H:i:s') . PHP_EOL;

$dateImmu = new DateTimeImmutable('2018-04-25');
echo 'DateTimeImmutable : ';
echo $dateImmu->modify('-14 day')->format('Y-m-d H:i:s') . PHP_EOL;
echo $dateImmu->modify('-30 day')->format('Y-m-d H:i:s') . PHP_EOL;
実行結果
DateTime : 2018-04-11 10:35:19
2018-03-12 10:35:19
DateTimeImmutable : 2018-04-11 10:35:19
2018-03-26 10:35:19

どちらも2018-04-25を起点にしていますが、実行結果が変わりましたね。
2018-04-25の30日前は2018-03-26なので、DateTimeImmutableクラスが正しい結果となります。

DateTimeクラスはミュータブルなため、14日前の日付を生成した際に、ベースの日付が変わってしまい、14日前の日付から30日前の日付を生成してしまっています。
DateTimeImmutableクラスはイミュータブルなため、14日前の日付を生成した際にも、ベースの日付が変わらず、ベースの日付から30日前の日付を生成しています。

以上のことから、

DateTimeクラス → 日付計算を行うときに注意が必要
DateTimeImmutableクラス → 日付計算もいい感じにしてくれる

と言えるかなと思います。

最後に

DateTimeクラスとDateTimeImmutableクラスでは、オブジェクト作成後の動きが違い、そのため特定の操作を行うときに挙動が変わることがわかりました。

自分は、DateTimeクラスで上記の動きにハマったことがあり、今回の調べてみました。
日々のちょっとした疑問も調べてみると良いことがあるなと思いました。

以上、最後まで読んで頂きありがとうございました。

Why do not you register as a user and use Qiita more conveniently?
  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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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