2010-04-05 18 views
82
$date1 = $date2 = new DateTime(); 
$date2->add(new DateInterval('P3Y')); 

Ahora $date1 y $date2 contienen la misma fecha - tres años a partir de ahora. Me gustaría crear dos fechas de tiempo separadas, una que se analiza desde una cadena y otra con tres años agregados a ella. Actualmente lo he pirateado de esta manera:¿Cómo copio en profundidad un objeto DateTime?

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

pero eso parece un hack horrendo. ¿Existe una forma "correcta" de copiar en profundidad un objeto DateTime?

Respuesta

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

Actualización:

Si desea copiar en lugar de hacer referencia a un objeto DT existente, utilice clone, no =.

+10

utilicé un nuevo DateTime en el ejemplo para demostrar el punto , pero por ahora supongo que DateTime se devuelve de una API opaca a la que no puedo volver a llamar. Por ejemplo, tengo una función que maneja pedidos que devuelve un DateTime que es cuando el cliente puede hacer un pedido. Llamar a la función para crear una copia produce efectos secundarios que no quiero. –

+0

No lo he probado realmente, pero se menciona en php.net que esto solo es aplicable para PHP 5.3 y superior. –

+0

@hugo: Sí, la clase DateTime requiere PHP 5.3. –

74

Clon de la fecha con el operador clone:

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

Los clones son poco profundas de manera predeterminada, pero lo suficientemente profundo para un DateTime. En sus propios objetos, puede definir el método mágico __clone() para clonar las propiedades (es decir, objetos secundarios) que tienen sentido para clonarse cuando el objeto primario cambia.

(no estoy seguro de por qué la documentación piensa que un buen ejemplo de la necesidad de clonar un objeto es GTK. ¿Quién utiliza GTK en PHP?)

+1

Gracias por la respuesta, pero ¿cómo sabes que es lo suficientemente profunda para DateTime? ¿Qué atributos siguen siendo referencias y cuáles se copian por valor? Por ejemplo, ¿puedo cambiar la hora y la zona horaria y no afectará el clon? – David

+1

@David: Sé que es lo suficientemente profundo para DateTime porque lo intenté, y funcionó para mí. No intenté cambiar la zona horaria ni ninguna otra cosa, solo la hora y la fecha básicas. – rjmunro

+3

Usando Xdebug, var_dump ($ date1) informa que contiene 'date' => string, 'timezone_type' => int & 'timezone' => string. Dado que no parece contener ninguna matriz u objeto, solo escalares básicos, un clon superficial debería estar bien. –

30

PHP 5.5.0 introdujo DateImmutable. add y modify métodos de esta clase devuelven nuevos objetos.

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

Tenga en cuenta que desafortunadamente no puede simplemente cambiar un 'DateTime' con un' DateTimeImmutable'.Hay al menos 'IntlDateFormatter :: formatObject' que no le gusta inmutables (devuelve' false' en lugar de la cadena formateada). – user276648

+1

¡oh! De alguna manera, nunca supe que existía, aunque siempre he soñado con eso. y todo el camino de regreso en 5.5 ... – Ben

+2

Al igual que algunos novatos Acabo de encontrar un obstáculo orientado a objetos modificando mi objeto 'DateTime' en un ciclo for: D Esto lo resolvió bien ... – Wilt

0

Debe cambiar su DateTime a DateTimeImmutable

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

continuación, puede llamar a cualquier método en la DateTime sin preocuparse de que cambie

+0

Esto es realmente una respuesta a una pregunta diferente. –

+0

@BillyONeal No podría haber explicado completamente cómo, pero esta es una solución a este problema ya que el origen de este problema es cómo llamar al método 'add' en' date2' cambia el valor de 'date1' y no hay forma de copia el valor de la variable 'DateTime' a menos que tengas un' DateTimeImmutable' –

Cuestiones relacionadas