Objeto DateTime: No más basuras con las fechas

Algún día el ser humano se unirá en una sola nación y se acabaran los problemas con fechas, encodings y demás miserias que todos hemos tenido que soportar en prácticamente todos los lenguajes de programación, especialmente cuando tenemos una aplicación web multi-lenguaje, multi-zonahoraria, etc…

Pero como este día está muy lejos, tenemos que intentar simplificar al máximo todo esto.

En cuanto al encoding, para mí no hay duda, todo en UTF-8, tanto archivos como tablas en la BBDD y como collation utf8_general_ci. Bien es cierto que si solamente vamos a usar caracteres europeos, el encoding ISO-8859-1 (o el 15 si vamos a usar el carácter €) es algo más óptimo a nivel almacenamiento, ya que los acentos, ñ, etc ocupan 2 bytes en utf-8 y 1 byte en iso-8859, pero al final si nuestra aplicación web crece tendremos problemas más gordos que todo esto.

Para las fechas, la verdad es que PHP ha sido siempre un poco desastre.
Tenemos desde hace mucho tiempo las funciones date, time, strtotime pero siempre había faltado un set de funciones para comparar y modificar fechas. Si trabajáis en temas de logística (para las franjas de envío), reservas de vuelos o hoteles o cualquier otro tipo de software que requiera trabajar exhaustivamente con fechas, probablemente os hayáis hecho alguna clase para manejar todo esto o seguramente vuestro framework favorito ya llevaba algo.

El objeto DateTime fue introducido en PHP5.2 pero la verdad es que ha pasado bastante desapercibido por la mayoría de Developers. En PHP5.3 este objeto ha sido bastante mejorado y la verdad es que una vez empiezas a usarlo, no puedes pasar sin él.

Ejemplo: Para obtener un objeto tiempo 2 días superior al instante actual

<?php
// Example 1: Get a date 2 months from now
 
$now = new \DateTime();
$twodaysfromnow = new \DateTime();
 
$twodaysfromnow->modify('+2 months');
 
echo 'Now it is '. $now->format('l, Y-F-d H:i:s') . 
     ' and in 2 months time it will be ' . 
     $twodaysfromnow->format('l, Y-F-d H:i:s') . PHP_EOL;
?>

Bastante fácil, no? 😀

Para crear un objeto DateTime a partir de un string

(por ejemplo sacado de Base de Datos)

<?php
// Example 2: Convert a String to a DateTime object
 
$str = '2011-08-13 13:25:00';
$objDT = \DateTime::createFromFormat('Y-m-d H:i:s', $str);
 
echo '$objDT is a ' . get_class($objDT) . ' object '. 
     ' storing date: ' . $objDT->format('l, Y-F-d H:i:s') . PHP_EOL;
?>

Para crear un objeto DateTime con los settings del momento actual excepto alguno

(Por ejemplo, esto puede servir para marcar una fecha fin a día de hoy a las 20h)

<?php
// Example 3: Get a DateTime object with value today but exactly at 8PM
 
$TodayAt8pm = \DateTime::createFromFormat('H', 20);
echo 'Today at 8PM: ' . $TodayAt8pm->format('Y-m-d H:i:s') . PHP_EOL;
?>

Y quizás la más potente: Diferencia entre objetos

<?php
// Example 4: Getting difference between objects
$today = new \DateTime();
 
// Maya's End of the World!
$worldend = \DateTime::createFromFormat('Y-m-d', '2012-12-21');
 
$timeLeft = $today->diff($worldend);
echo '$timeLeft is a ' . get_class($timeLeft) . ' object' . PHP_EOL;
 
echo $timeLeft->format('%a') . ' days left' . PHP_EOL;
echo $timeLeft->format('%y year(s), %m months, %d days') . ' left' . PHP_EOL;
?>

Lo “malo” es que diff nos devuelve un objeto DateInterval, y sus format son algo diferentes a los de un DateTime (ahhh PHP crazy things…). Podéis consultar las opciones aquí

Por cierto, comentar que desde hoy publicaré los snippets de código en mi GitHub, que podéis ver aquí.

También publicaré el código de algunas páginas que realizo. El primer experimento es con la refactorización de http://www.sylviaestruch.com actualmente a medio hacer, hecha en Kohana 3.0 y que reharé en Symfony2. Si estáis interesados en ver un proyecto pequeño pero totalmente hecho de 0 en Symfony2, estad atentos a este repositorio!

Proximamente más posts sobre PHP, Symfony2 y a ver si termino mi próxima entrega de la serie “Cómo hacer un framework ligero en PHP” que realmente es lo que me da más visitas aunque esté totalmente a medio hacer y experimental!

Hasta pronto!

You may also like...

3 Responses

  1. Cristian Martin says:

    Gracias por la información, tarde o temprano siempre acabas peleándote con las fechas (ya era hora que lo solucionaran, dicho sea de paso).

  2. tirengarfio says:

    Nice article!

  3. Alvarez says:

    muy pero muy buen post este sobre las fechas!! me sirvieron de mucho.. gracias :mrgreen: