Как сделать глубокую копию объекта DateTime?

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

Теперь $date1 и $date2 содержат ту же дату - через три года. Я хотел бы создать два отдельных периода времени, один из которых анализируется из строки и один с тремя годами, добавленными к нему. В настоящее время я взломал это следующим образом:

$date2 =  new DateTime($date1->format(DateTime::ISO8601));

но это кажется ужасным взломом. Есть ли "правильный" способ глубокой копии объекта DateTime?

Ответ 1

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

Update:

Если вы хотите скопировать, а не ссылаться на существующий объект DT, используйте clone, а не =.

$a = clone $b;

Ответ 2

Клонирование даты с помощью оператора clone:

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

Клоны по умолчанию мелкие, но достаточно глубокие для DateTime. В ваших собственных объектах вы можете определить магический метод __clone() для клонирования свойств (то есть дочерних объектов), которые имеют смысл клонировать, когда родительский объект изменяется.

(Я не уверен, почему документация считает хорошим примером необходимости клонирования объекта GTK. Кто использует GTK в PHP?)

Ответ 4

TLDR:

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

(мелкая копия смеется - глубокое копирование DateTime не имеет (в настоящее время) никакого смысла)

Все просто :)

Объяснение "php создает объект datetime из другого datetime":

  1. Ключевое слово clone делает обычную мелкую копию - для этого случая достаточно (почему => см. ниже)
  2. Обтекание его с помощью () оценивает выражение, возвращающее вновь созданный объект, по clone
  3. Поэтому вызывается ->modify() и модифицирует новый объект
  4. DateTime::modify(...) документы:

    Возвращает объект 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();

выходы:

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

поэтому нет ссылок, просто простые типы => нет необходимости глубокого копирования.

Ответ 5

Вы должны изменить свой DateTime на DateTimeImmutable

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

то вы можете вызвать любой метод на DateTime, не беспокоясь об этом.