bengamra
las 2 clases DateTime
y DateTimeImmutable
implementar la misma interfaz DateTimeInterface
. Por eso quiero saber:
Cuál es la diferencia entre estas 2 clases DateTime
y DateTimeImmutable
?
El_Vanja
El núcleo de la diferencia se describe en el documentación del DateTime
clase:
Esta clase se comporta igual que DateTimeImmutable excepto que los objetos se modifican cuando se llama a métodos de modificación como DateTime::modify().
Observemos esta diferencia en un ejemplo concreto:
$date = new DateTime();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');
Esto generará:
2021-05-15
2021-05-15
Lo que pasó aquí es que el modify
devolvió la misma instancia de la DateTime
objeto. La variable $tomorrow
no contiene un objeto diferente, contiene una referencia al original. La actualización de la nueva variable también modificó la original.
Si ejecutamos la misma modificación, pero en la versión inmutable:
$date = new DateTimeImmutable();
$tomorrow = $date->modify('+1 day');
echo $date->format('Y-m-d');
echo $tomorrow->format('Y-m-d');
Esto generará:
2021-05-14
2021-05-15
Porque en DateTimeImmutable
, los métodos de modificación no devuelven la misma instancia, le brindan una nueva (también inmutable). Esto también significa que debes asignar su resultado a una variable (como en el ejemplo anterior) para la versión inmutable para poder usarlo:
$date = new DateTime('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-15
$date = new DateTimeImmutable('2021-05-14');
$date->modify('+1 day');
echo $date->format('Y-m-d'); // 2021-05-14; original is untouched
Debido a este comportamiento, la versión inmutable debe preferirse a la mutable prácticamente siempre. La modificación accidental de una instancia de una fecha que no tenía la intención de modificar es un error bastante común.
Es posible que prefiera la versión mutable para evitar el paso de la asignación en situaciones en las que puede determinar de manera confiable que no hay peligro de comprometer el estado de su aplicación, pero es mejor dejar que se estime una vez que tenga una comprensión firme de los conceptos.
Aparte de modify
los siguientes métodos también se consideran mutantes:
add
sub
setDate
setISODate
setTime
setTimezone
-
Está un poco escondido en el documentaciónasí que tal vez sea bueno tener en cuenta que
Immutable->modify()
devuelve un nuevo Inmutable objeto. Así que cada subsiguientemodify()
en el nuevo objeto también tiene que ser asignado a una variable. Me tomó un tiempo averiguarlo.– Miguel
21 de enero a las 9:42
-
@Michel Agregué explícitamente que devuelve una versión inmutable. Aunque si lo piensas bien, no tendría ningún sentido si fuera de otra manera. Si su instancia inmutable de repente se volviera mutable, entonces se perdería todo el propósito de la inmutabilidad.
– El_Vanja
22 de enero a las 11:43
-
Este señor, es una muy buena respuesta. ¡Gracias! Ahora me pregunto por qué no he estado usando esto todo este tiempo…
– Naderio
13 abr a las 18:53
-
¡Muy buen artículo! ¡Gracias!
– Tim K.
15 de mayo a las 10:28
La diferencia está en la parte ‘inmutable’, lo que significa que una vez que se crea el objeto, nunca puede cambiar (wiki para más información). Lo que esto significa es que cada vez que modifique un DateTime
se cambiará la misma instancia, pero cuando modifique una DateTimeImmutable
en su lugar, se devolverá una nueva instancia modificada.
En general, un objeto inmutable nunca cambiará su estado después de haber sido creado. En cambio, cuando se necesita una modificación, devolverá una nueva instancia de la misma clase con el estado modificado.
El hecho de que ambos implementen el mismo Interfaz de fecha y hora es un poco confuso, pero puede explicarse por el hecho de que la interfaz no describe todas las funciones disponibles que el Fecha y hora y DateTimeImmutable oferta. Más precisamente, la interfaz no cubre métodos que permitan cambios de estado.
El caso de uso para elegir uno u otro depende principalmente de la preferencia, los estándares de codificación y, hasta cierto punto, la necesidad de calidad del código frente a la necesidad de velocidad de desarrollo.
Solo una nota rápida: si desea evitar el proceso de asignación, puede concatenar: echo $date->modify('+1 day')->format('Y-m-d');
asumiendo que $date
es el DateTimeImmutable
objeto.
Ejemplo:
$date = new DateTimeImmutable('2022-05-01');
$days = rand(2, 10);
echo "Date is: " . $date->format('d/m/Y')."\r\n";
echo "Now adding " .$days." days\r\n";
echo "Date now is: " . $date->modify('+'.$days.' day')->format('d/m/Y');