如何深度复制DateTime对象?

Bil*_*eal 114 php datetime

$date1 = $date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));
Run Code Online (Sandbox Code Playgroud)

现在$date1$date2包含相同的日期 - 三年后.我想创建两个单独的日期时间,一个用字符串解析,另一个用三年时间添加到字符串中.目前我已经像这样破解了它:

$date2 =  new DateTime($date1->format(DateTime::ISO8601));
Run Code Online (Sandbox Code Playgroud)

但这似乎是一个可怕的黑客.深度复制DateTime对象是否有"正确"的方法?

Amy*_*y B 157

$date1 = new DateTime();
$date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));
Run Code Online (Sandbox Code Playgroud)

更新:

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

$a = clone $b;

  • 我在示例中使用了一个新的DateTime来演示这一点,但是现在假设DateTime是从一些我不能再调用的不透明API中返回的.例如,我有一个处理订单的函数,该订单返回DateTime,即客户下次下订单时.调用函数创建副本会产生我不想要的副作用. (11认同)
  • 正当我认为我掌握了PHP时,我学习了一个新的操作符. (9认同)

rjm*_*nro 100

使用克隆运算符克隆日期:

$date1 = new DateTime();
$date2 = clone $date1;
$date2->add(new DateInterval('P3Y'));
Run Code Online (Sandbox Code Playgroud)

默认情况下,克隆很浅,但对于DateTime来说足够深.在您自己的对象中,您可以定义__clone()魔术方法来克隆在父对象更改时有意义克隆的属性(即子对象).

(我不确定为什么文档认为需要克隆对象的一个​​很好的例子是GTK.谁在PHP中使用GTK?)

  • 使用Xdebug,var_dump($ date1)报告它包含'date'=> string,'timezone_type'=> int&'timezone'=> string.由于它似乎不包含任何数组或对象,只是基本标量,浅层克隆应该没问题. (3认同)

Ale*_*den 44

PHP 5.5.0引入了DateTimeImmutable.添加修改此类的方法返回新对象.

$date1 = new DateTimeImmutable();
$date2 = $date1->add(new DateInterval('P3Y'));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,遗憾的是,您不能只使用`DateTimeImmutable`交换`DateTime`.至少`IntlDateFormatter :: formatObject`不喜欢immutables(返回`false`而不是格式化的字符串). (4认同)
  • @ user276648此错误现已在php 7.1.5中修复http://www.php.net/ChangeLog-7.php#7.1.5 (3认同)
  • 就像一些菜鸟我刚刚通过修改for循环中的`DateTime`对象遇到了面向对象的陷阱:D这很好地解决了它...... (2认同)

jav*_*web 9

TLDR:

$date1 = new DateTime();
$date2 = (clone $date1)->modify('+3 years');
Run Code Online (Sandbox Code Playgroud)

(浅拷贝被调用- 深度复制DateTime(当前)没有意义

就那么简单 :)

说明“ php从另一个日期时间创建日期时间对象”:

  1. clone关键字使常规拷贝- enaugh此情况下(为什么=>见下文)
  2. 将其包装起来可以()计算返回新创建对象的表达式clone
  3. ->modify() 因此被调用并修改新对象
  4. DateTime::modify(...) docs:

    返回DateTime对象以进行方法链接或失败时返回FALSE。

  5. $date2现在包含新创建和修改的克隆/副本,而$date1保持不变

为什么您不需要在这里进行复制:

仅当需要复制作为引用的属性的目标时,才需要深度复制/克隆,但这是:

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();
Run Code Online (Sandbox Code Playgroud)

输出:

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

因此没有引用,只是简单的类型=>无需深度复制。