40

The 2 classes DateTime and DateTimeImmutable implement the same interface DateTimeInterface. Therefore I want to know :

What is the difference between these 2 classes DateTime and DateTimeImmutable?

yivi
  • 42,438
  • 18
  • 116
  • 138
hbgamra
  • 749
  • 1
  • 6
  • 18

3 Answers3

94

The core of the difference is described in the documentation of the DateTime class:

This class behaves the same as DateTimeImmutable except objects are modified itself when modification methods such as DateTime::modify() are called.

Let's observe this difference on a concrete example:

$date = new DateTime();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');

This will output:

2021-05-15
2021-05-15

What happened here is that the modify returned the same instance of the DateTime object. The variable $tomorrow doesn't contain a different object, it contains a reference to the original one. Updating the new variable modified the original one as well.

If we execute the same modification, but on the immutable version:

$date = new DateTimeImmutable();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');

This will output:

2021-05-14
2021-05-15

Because in DateTimeImmutable, the modification methods don't return the same instance, they give you a fresh one (also immutable). This also means that you must assign its result to a variable (like in the previous example) for the immutable version in order to use it:

$date = new DateTime('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-15

$date = new DateTimeImmutable('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-14; original is untouched

Due to this behaviour, the immutable version should be preferred over the mutable one virtually always. Accidentally modifying an instance of a date you didn't mean to modify is quite a commonly occurring bug.

You might prefer the mutable version to avoid the step of assignment in situations where you can reliably determine there is no danger of compromising the state of your application, but that is best left to be estimated once you have a firm grasp on the concepts.

Aside from modify, the following methods are also considered as mutating:

  • add
  • sub
  • setDate
  • setISODate
  • setTime
  • setTimezone
El_Vanja
  • 3,660
  • 4
  • 18
  • 21
  • 5
    It's a bit hidden in the [documentation](https://www.php.net/manual/en/datetimeimmutable.modify.php), so perhaps good to note that `Immutable->modify()` returns a new **Immutable** object. So every subsequent `modify()` on the new object also has to be assigned to a variable. Took me a while to find out. – Michel Jan 21 '22 at 09:42
  • @Michel I explicitly added that it returns an immutable version. Though if you think about it, it wouldn't make any sense if it did otherwise. If your immutable instance suddenly turned mutable, then the whole purpose of immutability would be lost. – El_Vanja Jan 22 '22 at 11:43
  • 2
    This sir, is a really good answer. Thank you! Now i wonder why i have not been using this all along... – Naderio Apr 13 '22 at 18:53
  • Very good article! Thanks! – Tim K. May 15 '22 at 10:28
  • 1
    @Naderio because a) `DateTimeImmutable` came a little later (PHP 5.5+, so basically 5.6+) b) people don't like to "re-assign" - however those are not excuses, there's also c) some people argue around unnecessary cloning when e.g. chaining more modifications. – jave.web Feb 09 '23 at 17:54
11

The difference is in the 'immutable' part, which means once the object is created it can never change (wiki for more info). What this means is that whenever you'd modify a DateTime the same instance will be changed, but when you modify a DateTimeImmutable a new modified instance will be return instead.

In general an immutable object will never change it's state after being created. Instead when a modification is needed it will return a new instance of the same class with the modified state.

The fact that these both implement the same DateTimeInterface is a bit confusing, but can be explained by the fact that the interface does not describe all available functions that the DateTime and DateTimeImmutable offer. More precisely the interface does not cover methods which allow for state changes.

The use case for picking either one or the other mostly depends on preference, coding standards and, to some degree, need for code quality vs need for speed of development.

PtrTon
  • 3,705
  • 2
  • 14
  • 24
1

Just a quick note: if you want to avoid the assignment process you can concatenate: echo $date->modify('+1 day')->format('Y-m-d'); assuming that $date is the DateTimeImmutable object.

Example:

$date = new DateTimeImmutable('2022-05-01');
$days = rand(2, 10);

echo "Date is: " . $date->format('d/m/Y')."\r\n";
echo "Now adding " .$days." days\r\n";
echo "Date now is: " . $date->modify('+'.$days.' day')->format('d/m/Y');
Alberto Ar3s
  • 311
  • 1
  • 3
  • 14