DateTimeImmutable vs DateTime
Solution 1:
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
Solution 2:
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.