El formateo de fechas es una cuestión importante para un CMS. Veamos a continuación algunos modos en que puede llevarse a cabo esta tarea en PHP.

Para el posterior analisis, vamos a plantear tres cuestiones que nos parecen importantes a tener en cuenta:

  1. La declaración del formato debe ser lo más sencilla posible.
  2. El formato se debe poder traducir a distintos idiomas.
  3. No alcanza con que el formato pueda ser traducido, la declaración del formato debe poder modificarse dependiendo del idioma.

Muy bien, comencemos entonces. PHP tiene dos modelos para darle formato a las fechas.

El primer modelo lo utiliza la función date, la interfaz DateTimeInterface y todas las clases que la extienden. Es sencillo, pero la salida es en inglés.

El segundo modelo lo introduce la función strftime. La ventaja es que tiene en cuenta la configuración local, aunque depende del servidor. La desventaja es que los comandos están precedido por el signo %, lo que genera algo de ruido.

 

Y entonces?

Particularmente me quedo con el primer modelo, apostando a su sencillez y a que es posible, como veremos a continuación, traducir la salida y aún, modificar la declaración del formato.

 

Traducir la fecha

El siguiente es un modo sencillo de traducir las fechas a través de expresiones regulares. Aclaramos que se da por supuesto que existe una función gettext o similar capaz de traducir la palabra hallada. 

function i18n_date_format($format, $timestamp = false)
{
  $output = date($format, $timestamp);
  $pattern = '#'.
    // week
    'Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?|'.
    // months
    'Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|'.
    'Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?'.'#';
		
  return preg_replace_callback($pattern, function($match) {
    return gettext($match[0]);
  }, $output);
}

La función es válida si no fuera por el mes de mayo, que en ingés tiene 3 letras y hace imposible saber si está declarada su versión corta o completa. Un modo de corregir esto es analizando el formato de entrada. Otro modo es cambiando el formato de entrada por otro ligeramente diferente que mantenga la información necesaria, por ejemplo, de la siguiente manera:

$format = preg_replace('#(?<!\\\\)+(M|F)#', '\1:\\\\\\1', $format);
// d-M-Y -> d-M:\M-Y
$output = date($format, $timestamp);

Si el formato contiene una M o F se le agregará a continuación, separado por dos puntos, el mismo caracter escapado. Este último dato puede ser captado y utilizado de la siguiente manera:

function i18n_date_format($format, $timestamp = false)
{
  $format = preg_replace('#(?<!\\\\)+(F|M)#', '\1:\\\\\\1', $format);
  $output = date($format, $timestamp);
  $pattern = '#('.
    // week
    'Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?|'.
    // months
    'Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|'.
    'Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)(?::(F|M))?'.'#';
		
  return preg_replace_callback($pattern, function($match) {
    if (isset($match[2])) { // is month
      return $match[2] == 'M' 
           ? gettext('short_' . $match[1])
           : gettext('full_' . $match[1]);
    } else { // is day
      return gettext($match[1]);
    }
  }, $output);
}

 

Modificar la declaración del formato según el idioma

La mejor forma de cambiar algo según el idioma es a través del sistema que uno elige para tal fin. Esto significa que, si por ejemplo se elige gettext, debemos encadenar las funciones de la siguiente manera:

$date = i18n_date_format(gettext('d-M-Y'));

 

Conclusión

Como hemos demostrado, es posible tener fechas con un alto grado de personalización y un costo mínimo.