How do I deep copy a DateTime object?
PhpDatetimePhp Problem Overview
$date1 = $date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));
Now $date1
and $date2
contain the same date -- three years from now. I'd like to create two separate datetimes, one which is parsed from a string and one with three years added to it. Currently I've hacked it up like this:
$date2 = new DateTime($date1->format(DateTime::ISO8601));
but that seems like a horrendous hack. Is there a "correct" way to deep copy a DateTime object?
Php Solutions
Solution 1 - Php
$date1 = new DateTime();
$date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));
Update:
If you want to copy rather than reference an existing DT object, use clone
, not =
.
$a = clone $b;
Solution 2 - Php
Clone the date with the clone operator:
$date1 = new DateTime();
$date2 = clone $date1;
$date2->add(new DateInterval('P3Y'));
Clones are shallow by default, but deep enough for a DateTime. In your own objects, you can define the __clone()
magic method to clone the properties (i.e. child objects) that make sense to be cloned when the parent object changes.
(I'm not sure why the documentation thinks a good example of needing to clone an object is GTK. Who uses GTK in PHP?)
Solution 3 - Php
PHP 5.5.0 introduced DateTimeImmutable. add and modify methods of this class return new objects.
$date1 = new DateTimeImmutable();
$date2 = $date1->add(new DateInterval('P3Y'));
Solution 4 - Php
TLDR (PHP 5.5+ / 7.0.0+ / 8.0.0+):
Use DateTimeImmutable
: it does not alter the original instance :-)
<?php
$date1 = new DateTimeImmutable(); // Immutable => VERY IMPORTANT
$date2 = $date1->modify('+3years');
// see that $date1 still has the original year
echo $date1->format('Y-m-d H:i:s'); // outputs 2022-05-01 12:59:50
echo PHP_EOL;
echo $date2->format('Y-m-d H:i:s'); // outputs 2025-05-01 12:59:50
BTW: If you use Carbon
there is also CarbonImmutable
PHP docs: https://www.php.net/manual/en/class.datetimeimmutable.php
Simple as that :)
Old answer(rewritten) (don't recommend anymore!):
Shallow copy used to be enough - Deep copy-ing DateTime didn't make sense back then, since we could easily introspect the DateTime instance and see that there were only simple types that are copied by value (there were no references).
Following code however stopped working in PHP7.4 (most likely the future solution will be somewhere around Reflection class/object),
class TestDateTime extends DateTime{
public function test(){
//*this* way also outputs private variables if any...
var_dump( get_object_vars($this) );
}
}
$test = (new TestDateTime())->test();
used to output
array(3) {
["date"]=>
string(26) "2019-08-21 11:38:48.760390"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
so there are no references, just simple types => there was no real reason to deep copy, however I don't recommend using this anymore in the future.
Solution 5 - Php
You should change your DateTime
to DateTimeImmutable
// from date time
$date = \DateTimeImmutable::createFromMutable($mutableDate)
then you can call any method on the DateTime
without worrying about it change