fLIPIS
   

Funciones de cadena para fechas


      
Aunque el formato de tiempo unix es muy conviente, es muy raro que los programadores trabajemos en entornos totalmente convenientes, especialmente cuando tenemos que integrar bases de datos de terceros con las nuestras propias. Es por ello que, debido a que tanta gente almacena las fechas de formas tan diferentes, vamos a dedicar este capítulo a analizar formas diferentes de traducir diferentes formatos de fecha a instantes unix para que nos resulten mas sencillas de trabajar. Por supuesto, para todo aquel que prefiera seguir usando campos TIMESTAMP, toda la siguiente información puede seguir resultando muy útil con una simple llamada a date() que lo transforme en una cadena formateada como los TIMESTAMP que hemos visto al principio del tutorial.
      
Comenzaremos con la función strftime(), que escribe una fecha en formato de texto acorde a unos parémtros. Veamos un ejemplo de su uso:
   
   
<?php

setlocale(LC_TIME, "spanish");   //En plataformas Windows
//setlocale(LC_TIME, "es_ES");   Plataformas UNIX
echo strftime("%A, %B de %Y");

?>
      
Esto devolverá el día de hoy en formato castellano. En plataformas Windows, tenemos que utilizar setlocale con el último parámetro a "spanish", ver Mensaje de pigmeu at pigmeu dot net para mas información. setlocale() es una función que nos permite especificar diferentes tipos de formateo de cadenas en un idioma concreto. Mirad la documentación para ver lo que hace, de momento nos centraremos en strftime(). Esta función admite un segundo argumento, el instante unix que queremos formatear en tiempo. Encapsulemos un poco nuestra llamada a strftime de tal forma que podamos pasarle una serie de parámetros de cadena:
   
timetool.class.php
   
<?php
define ("FULL_STR_SPANISH_DATE", "%A , %d de %B del %Y, a las %H horas, %M minutos y %S segundos");
define ("STR_SPANISH_DATE", "%A, %B de %Y");

//Página 3
setlocale(LC_TIME, "spanish");   //En plataformas Windows
echo LittleTimeTool::makeStringTime(STR_SPANISH_DATE, LittleTimeTool::gimmeSomeTime())."<br>";
echo LittleTimeTool::makeStringTime(FULL_STR_SPANISH_DATE, LittleTimeTool::gimmeSomeTime(0, 10))."<br>";
echo LittleTimeTool::makeStringTime(FULL_STR_SPANISH_DATE, LittleTimeTool::gimmeSomeTime(0, 0, 0, 2))."<br>";
echo LittleTimeTool::makeStringTime(FULL_STR_SPANISH_DATE, LittleTimeTool::gimmeSomeTime(0, 0, 0, -2, -4, -5))."<br>";
?>
      
De la misma forma que llamábamos a date(), ahora llamaremos a strftime() con los segundos que saquemos de las llamadas a nuestra clase. Como vemos, las cadenas de texto quedan perfectamente legibles para fomatos profesionales, con lo que vemos otra aplicación del instante de unix en este contexto. El problema para las fechas en formato castellano es que la función strtotime(), que transforma fechas desde cadena a instantes de unix, no funciona si tenemos las fechas puestas en castellano, solo sabe parsear fechas en inglés. Así que, ¿qué haríamos para poder parsear una fecha desde nuestro formato a un instante de unix? Una solución es lo que se expone a continuación:
   
timetool.class.php
   
<?php
public static function makeUnixFromStringTime($stringTime, $timeFormat)
{
   if($timeFormat == FULL_STR_SPANISH_DATE)
   {
      $regExp = "/([a-zA-Z]+),[\s]([0-9]+)[\s][a-z]+[\s]([a-zA-Z]+)[a-z\s]+([0-9]+),[a-z\s]+([0-9]+)[a-z\s]+,[\s]([0-9]+)[a-z\s]+([0-9]+)[a-z\s]+/";
      preg_match($regExp, $stringTime, $matches);
      //$matches[1] -> nombre del dia
      //$matches[2] -> numero del dia
      //$matches[3] -> nombre del mes
      //$matches[4] -> numero de año
      //$matches[5] -> Hora
      //$matches[6] -> minuto
      //$matches[7] -> Segundo
      
      if(count($matches) != 8)
      {
         throw new Exception("LA CADENA NO CASA CON LA EXPRESION REGULAR");
      }
      else
      {
         $firstArg = intval($matches[5]);
         $secondArg = intval($matches[6]);
         $thirdArg = intval($matches[7]);
         $fifthArg = intval($matches[2]);
         $sixthArg = intval($matches[4]);
         $mes = $matches[3];   
      }
   }
   else
   {
      $regExp = "/([0-9]+)[\s][a-z]+[\s]([a-zA-Z]+)[\s][a-z]+[\s]([0-9]+)/";
      preg_match($regExp, $stringTime, $matches);
      //$matches[1] -> Día
      //$matches[2] -> Nombre de mes
      //$matches[3] -> Año 
      if(count($matches) != 4)
      {
         throw new Exception("LA CADENA NO CASA CON LA EXPRESION REGULAR");
      }
      else
      {
         $firstArg = 0;
         $secondArg = 0;
         $thirdArg = 0;
         $fifthArg = intval($matches[1]);
         $sixthArg = intval($matches[3]);
         $mes = $matches[2];   
      }
      echo "<pre>";
      echo $stringTime."<br/>";
      print_r($matches);
      echo "</pre>";
   }
      
   switch(strtolower($mes))
   {
      case "enero":
         $fourthArg = 1;
         break;
         
      case "febrero":
         $fourthArg = 2;
         break;
         
      case "marzo":
         $fourthArg = 3;
         break;
         
      case "abril":
         $fourthArg = 4;
         break;
         
      case "mayo":
         $fourthArg = 5;
         break;
         
      case "junio":
         $fourthArg = 6;
         break;
         
      case "julio":
         $fourthArg = 7;
         break;
         
      case "agosto":
         $fourthArg = 8;
         break;
         
      case "septiembre":
         $fourthArg = 9;
         break;
         
      case "octubre":
         $fourthArg = 10;
         break;
         
      case "noviembre":                  
         $fourthArg = 11;
         break;
         
      case "diciembre":
         $fourthArg = 12;
         break;                  
   }   
   
   return mktime($firstArg, $secondArg, $thirdArg, $fourthArg, $fifthArg, $sixthArg);
}
?>
      
Este enrevesado método lo que hace es cortar, a través de una expresión regular, una fecha en el formato especificado en las constantes STR_SPANISH_DATE y FULL_STR_SPANISH_DATE, y aunque no es ni de lejos tan potente como strtotime(), nos puede llegar a ser bastante útil si, a partir de una fecha en formato de cadena, queremos sacar el instante unix asociado. Con meter mas expresiones regulares para cazar diferentes formatos de fecha lo tendríamos resuelto. El switch largo es porque como tenemos el mes en formato de texto, tenemos que poder sacar su valor numérico de alguna forma.
      
Y de momento, hasta aquí llega este tutorial sobre tiempo en PHP. Espero que apreciéis la utilidad del instante unix en cuanto a poder medir el tiempo de una forma distinta que con cadenas y campos TIMESTAMP. Si en algún momento os es necesario un campo de este tipo, o cogéis una base de datos que lo contenga, con estos fragmentos de código y unas cuantas visitas a la documentación de PHP no os faltará información para trabajar con este tipo de dato. Hasta el próximo tutorial, un saludo de fLIPIS.