How do I deep copy a DateTime object?

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

105815 次浏览
$date1 = new DateTime();
$date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));

更新:

如果要复制而不是引用现有的 DT 对象,请使用 clone,而不是 =

$a = clone $b;

使用 克隆人操作符克隆日期:

$date1 = new DateTime();
$date2 = clone $date1;
$date2->add(new DateInterval('P3Y'));

默认情况下,克隆是浅层的,但对于 DateTime 来说已经足够深了。在您自己的对象中,您可以定义 __clone()神奇方法来克隆在父对象更改时有意义被克隆的属性(即子对象)。

(我不知道为什么文档认为需要克隆对象的一个好例子是 GTK。谁在 PHP 中使用 GTK?)

PHP 5.5.0引入了这个类的 日期时间不变.修改方法返回新对象。

$date1 = new DateTimeImmutable();
$date2 = $date1->add(new DateInterval('P3Y'));

你应该把你的 DateTime改成 DateTimeImmutable

// from date time
$date = \DateTimeImmutable::createFromMutable($mutableDate)

然后您可以调用 DateTime上的任何方法,而不用担心它的变化

TLDR (PHP 5.5 +/7.0.0 +/8.0.0 +) :

使用 DateTimeImmutable: 它不会改变原始实例 : -)

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

顺便说一下: 如果你使用 Carbon,也有 CarbonImmutable

PHP 文档: https://www.php.net/manual/en/class.datetimeimmutable.php

就这么简单:)

旧答案(重写)(不再推荐!) :

浅拷贝曾经就足够了——深拷贝 DateTime 在当时是没有意义的,因为我们可以很容易地内省 DateTime 实例,看到只有简单的类型被值拷贝(没有 参考文献)。

然而,下面的代码在 PHP7.4中停止工作(未来的解决方案很可能在反射类/对象附近) ,

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

用来输出

array(3) {
["date"]=>
string(26) "2019-08-21 11:38:48.760390"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}

所以没有引用,只有简单的类型 = > 没有真正的理由复制 很深,然而 我建议以后不要再使用这个