How do I deep copy a DateTime object?

PhpDatetime

Php 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBilly ONealView Question on Stackoverflow
Solution 1 - PhpAmy BView Answer on Stackoverflow
Solution 2 - PhprjmunroView Answer on Stackoverflow
Solution 3 - PhpAlexander GardenView Answer on Stackoverflow
Solution 4 - Phpjave.webView Answer on Stackoverflow
Solution 5 - PhpHossein ShahdoostView Answer on Stackoverflow