How do I deep copy a DateTime object?

Solution 1:

$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:

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 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:

TLDR:

$date1 = new DateTime();
$date2 = (clone $date1)->modify('+3 years');

(Shallow copy is enaugh - Deep copy-ing DateTime makes (currently) no sense)

Simple as that :)

Explanation "php create datetime object from another datetime":

  1. The clone keyword makes regular shallow copy - enaugh for this case (why => see below)
  2. Wraping it with () evaluates the expression returning the newly created object by clone
  3. ->modify() is therefore called on and modifies the new object
  4. DateTime::modify(...) docs:

    Returns the DateTime object for method chaining or FALSE on failure.

  5. $date2 now contains the newly created & modified clone/copy, while $date1 remains unchanged

Why you don't need to deep copy here:

Deep copy/clone is only necessary, when you need to copy targets of properties that are references, but this:

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();

outputs:

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 => no need to deep copy.