Los 10 Frameworks PHP que solicitan las empresas
Información sobre los frameworks más usados en PHP, aprende lo necesario para saber qué hace cada uno.
En este artículo verás de forma práctica cómo manejar fechas en PHP, lo que te ayudará en tu desempeño profesional con este lenguaje de programación.
La razón de más de un refunfuño de cualquier programador (novato o experimentado), es el tratamiento de fechas.
La irregularidad de nuestro calendario, sumado a las diferentes formas de representación (Día-Mes-Año, Año-Mes-Día, etc…) hacen que algo que debería ser trivial se convierta en una gran pérdida de tiempo y frustración.
Esto sucede en casi cualquier lenguaje de programación y PHP no es la excepción… ¿o sí?
Como de costumbre en PHP, las opciones son varias. Queda a criterio de cada desarrollador seleccionar, entre ellas, cuál es la más conveniente ante cada escenario.
Algunas opciones que se me vienen a la mente son:
El principal problema que vas a encontrar si intentas usar tu propia estructura de datos es que los cálculos y comparaciones serán realmente un dolor de cabeza (tendrás que programar un montón de operaciones que ya están resueltas si usas algunas herramientas propias del lenguaje).
Algo que puede aliviarte un poco (si elegís esta opción) es usar la versión estructurada del manejo de fechas de PHP: las funciones getdate y familia.
No está mal como primer paso… pero puedes ir todavía un poco más allá y realmente aprovechar el poder que tienes entre manos.
DateTime es una librería que ya viene incorporada a PHP (Al menos a partir de la versión 5… teniendo en cuenta que al momento de la escritura de este artículo la versión recomendada es la 7.1, creo que puedo asumir sin mucho miedo a equivocarme que estás usando una versión que soporta este tipo de datos…).
Esta librería trae consigo unas cuantas clases sumamente interesantes. Entre ellas:
Veamos de qué se tratan y cómo podés beneficiarte de usar cada una.
Esta es la clase que da nombre a toda la librería. Podríamos decir que es la principal.
Como te podrás imaginar, su objetivo es representar fechas en un formato compatible con POO.
Su principal característica es la versatilidad de su constructor.
Podemos hacer algo muy convencional como construir una fecha de este modo:
$d = new DateTime("2017/12/22");
O bien algo un poco más loco como:
$d = new DateTime("now");
En este caso el objeto $d
contendrá la fecha de hoy. Este efecto puede lograrse también invocando al constructor sin parámetros.
Pero lo que casi me hizo aplaudir de pié cuando lo descubrí es la posibilidad de usar cadenas escritas en lenguaje natural, como por ejemplo last day of this month
(Y sí… hay que saber un poco de Inglés :).
Por ejemplo, estoy escribiendo esto el 12 de Julio de 2017 y al ejecutar este comando:
$d = new DateTime('last day of this month')
El objeto $d
contiene la fecha 2017-06-30
.
Otros ejemplos interesantes de cadenas que puedes usar para crear fechas son:
yesterday
last friday
third thursday of next month
-60 day
En fin, las posibilidades son realmente amplias… podés consultar una guía completa aquí.
El método format te permite obtener una representación de una fecha como una cadena de caracteres, pero no siempre la misma cadena si no aquella que se ajuste a tu necesidad particular (Por ejemplo, podrías permitir a cada usuario de tu sitio decidir cómo quiere ver las fechas que les correspondan).
El modo de hacer esto consiste en pasar como parámetro al método format una cadena que especifique cómo debe estar conformada la cadena que debe ser generada.
Por ejemplo, para mostrar una fecha en formato día/mes/año harías algo como esto:
$d = new DateTime();
echo $d->format('d-m-y');
Si quisieras ver el nombre del mes (en lugar del número), podrías usar la cadena d-M-Y
.
Si quisieras ver algo del estilo 9:56pm on Wednesday 12th July 2017
podrías usar la cadena 'g:ia \o\n l jS F Y'
.
Las opciones son amplias, podés consultar ayuda aquí.
Algo interesante a tener en cuenta es como esa característica tan controvertida de PHP que es la conversión automática entre tipos de datos compatibles (Por ejemplo, "2"
y 2
) puede ayudarte a hacer cálculos.
Pensá en un ejemplo como este:
$d = new DateTime();
$dia = $d->format('d');
$manana = $dia + 1;
Estos métodos permiten adicionar o sustraer una unidad de tiempo a un objeto DateTime. Veremos más detalles en un momento (Cuando hablemos de la clase DateInterval).
Este método permite calcular la diferencia entre una fecha y otra (Por ejemplo para poder calcular cuántos días faltan para tu cumpleaños):
$d = new DateTime();
$diff = $d->diff($fechaCumple);
El resultado de esta operación es un objeto de clase DateInterval.
Esta clase es especialmente útil cuando se trata de realizar cálculos sobre fechas.
Por ejemplo, si tuvieras que hacer un sistema que envíe algún tipo de recordatorio 30 días a partir de una fecha, necesitarías calcular a qué fecha corresponde ese día.
Para hacer esto usando estas dos clases puedes usar un código de este estilo:
$d->add(new DateInterval('P30D'));
Se explica por si mismo, ¿cierto? :)
Ok, voy a darte algo más de detalle: lo que se está haciendo es llamar al método add
sobre $d
(Asumamos que ese objeto contiene la fecha incial) pasándole como parámetro un nuevo objeto de clase DateInterval, el cual se construye utilizando la cadnea 'P30D'
.
¿Por qué esa cadena en particular? Es una regla que usa esta clase (DateInterval) que significa lo siguiente:
Es decir, estamos construyendo un intervalo que corresponde a un período de 30 días.
Es posible construir intervalos de tiempo basados en meses, años, minutos, horas, etc… (Podés ver la información completa aquí).
Esto sólo ya debería convencerte de usar estas clases en lugar de cualquier otra alternativa disponible… ¿todavía no te convencí al 100%? Seguí leyendo :).
Típico problema de manejo de fechas es calcular el día siguiente de una fecha cualquiera (¿Y si es fin de mes? ¿Y si es fin de año?).
Con el método add y DateInterval todo está resuelto mágicamente:
$d->add(new DateInterval('P1D'));
Del mismo modo podés ir hacia atrás (Usando el método sub):
$d->sub(new DateInterval('P1D'));
Un método interesante que ofrece esta clase es format. Usándolo podés obtener una representación de un intervalo como una cadena:
$d = new DateTime();
echo $d->diff(new DateTime('first day of this month'))->format('%d dias');
Si te toca trabajar con diferentes zonas horarias a la vez no desesperes, la clase DateTimeZone
está ahí para ayudarte.
Como siempre, la referencia obligada es php.net.
Un ejemplo ilustrativo:
$t1 = new DateTime("first day of this month", new DateTimeZone('Asia/Bahrain'));
$t2 = new DateTime("first day of this month", new DateTimeZone('America/Argentina/Buenos_Aires'));
echo ($t1->diff($t2))->format('%d dias').PHP_EOL;
Da como resultado 1 dias
(Aparentemente Bahrain dista bastante de Buenos Aires :)
Si te tocara desarrollar algún tipo de aplicación que necesitara contar con un conjunto de fechas separadas entre sí por algún valor fijo (Por ejemplo, algo que sucede una vez cada 20 días), te podría ser útil la clase DatePeriod.
De lo que se trata esta clase es, precisamente, de modelar de un modo sencillo una serie de fechas correlacionadas. Por ejemplo:
$i = new DateInterval('P1D');
$d1 = new Datetime();
$p = new DatePeriod($d1, $i, 5);
foreach($p as $d) {
echo $d->format('Y-m-d H:i:s') . "\n";
}
Dará como resultado los próximos 5 días.
Otra forma de crear un intervalo es definiendo la fecha de inicio y la de fin:
$i = new DateInterval('P1D');
$d1 = new Datetime();
$d2 = clone $d1;
$d2->add(new DateInterval('P5D'));
$p = new DatePeriod($d1, $i, $d2);
foreach($p as $d) {
echo $d->format('Y-m-d H:i:s') . "\n";
}
Otra clase que puede resultarte útil cuando manejes fechas en tu aplicación es DateTimeImmutable
. DateTimeImmutable es prácticamente indistinguible de DateTime, excepto por el hecho de que los métodos que se invocan sobre sus instancias no las modifican (A diferencia de DateTime).
Un problema con el que puedes encontrarte es el hecho de que las clases DateTime
y DateTimeImmutable
no son libremente intercambiables, con lo cual, si un método espera recibir un objeto fecha debés pasar el tipo específico.
Para evitar estas situaciones desagradables existe la interface DateTimeInterface
. Si necesitas hablar genéricamente de fechas, podés usarla (Ya que es implementada tanto por DateTime como por DateTimeImmutable).
Esto es especialmente útil cuando estés creando tu propia función que necesita recibir una fecha y no importa si es o no modificable.
Un problema bastante molesto que tenía con un desarrollo para un cliente de Leeway era el hecho de que se necesitaba, en cualquier momento, tener los datos del último trimestre.
Así es como calculé las fechas del intervalo:
$fechaUltimoMes = new DateTime('-1 month');
$m = $fechaUltimoMes->format('m');
$ultimoCuatrimestre = floor($fechaUltimoMes->format('m') / 4) + 1;
$anioUltimoCuatrimestre = $fechaUltimoMes->format('Y');
$desdeFecha = new \DateTime( $anioUltimoCuatrimestre.'-'.$m.'-01');
$hastaFecha = clone $desdeFecha;
$hastaFecha
->add(new \DateInterval('P3M'))
->sub(new \DateInterval('P1D'));
echo "Desde: ".$desdeFecha->format('d/m/y')." hasta: ".$hastaFecha->format('d/m/y').PHP_EOL;
Corriéndolo hoy el resultado que obtengo es Desde: 01/06/17 hasta: 31/08/17
.
No está mal, ¿eh?
Si ves nuevamente el código que vengo usando, cuando hago add
por ejemplo, el resultado de la operación es un objeto DateTime, pero no cualquier objeto si no el objeto sobre el que haya invocado el método en cuestión (Para permitir las operaciones encadenadas).
Otra opción para lograr el mismo resultado sería esta:
$fechaUltimoMes = new DateTime('-1 month');
$m = $fechaUltimoMes->format('m');
$ultimoCuatrimestre = floor($fechaUltimoMes->format('m') / 4) + 1;
$anioUltimoCuatrimestre = $fechaUltimoMes->format('Y');
$desdeFecha = new \DateTimeImmutable( $anioUltimoCuatrimestre.'-'.$m.'-01');
$hastaFecha = $desdeFecha
->add(new \DateInterval('P3M'))
->sub(new \DateInterval('P1D'));
echo "Desde: ".$desdeFecha->format('d/m/y')." hasta: ".$hastaFecha->format('d/m/y').PHP_EOL;
En este caso el resultado de las operaciones add
y sub
no es un DateTime
si no un DateTimeImmutable
.
Como habrás visto, el manejo de fechas que PHP pone a tu disposición es realmente versátil y poderoso… no pierdas tu tiempo reinventando la rueda, aprende a sacarle el máximo provecho a la herramienta que estás usando.
¿Cuál ha sido tu desafío más importante cuando te tocó tratar con fechas en PHP? ¿Encontraste algo en este artículo que te habría hecho la vida más fácil? ¡Coméntalo!
También te puede interesar
Información sobre los frameworks más usados en PHP, aprende lo necesario para saber qué hace cada uno.