Mostrar una fecha sin mostrarla, de forma amigable, con PHP

Mostrar el tiempo de forma amigable, como Facebook o Twitter es una buena idea, sobretodo sobre todo si el lapso de tiempo entre el actual y el que se quiere mostrar no es demasiado largo. Si en vez de mostrar “14/11/1988 10:30” mostramos “Hace 21 años” puede parecer un poco exagerado y en ese caso yo mostraría algo como “Hace 21 años (el 14/11/1988)”. Pero si es algo que se actualiza con más frecuencia, como los estados de Twitter, Facebook y cualquier otra red social, donde es normal que no pasen más de 4 horas entre cada actualización y muy pocas veces pasa de un día, es mejor poner “Hace 34 minutos” que poner la hora en que se hizo, resulta más entendible para el usuario y da una imagen de dinamismo que el modo convencional no es capaz. Y el motivo es sencillo, cuando el usuario ve “a las 13:30” lo que hace es mirar la hora actual y calcular el lapso de tiempo… es decir, que mostrando la fecha de forma amigable lo que hacemos es evitarle al usuario la necesidad de pensar.

En Intenta han publicado su propia versión del snippet que iba a publicar yo hoy mismo – se me ha adelantado por unas horas… – , pero a su manera.  Y como el mío es algo diferente – los dos parten de la misma función nicetime() – lo publico igualmente.

En cualquier caso, la función original la escribió un tal yasmary en los comentarios de la documentación de php, y esto es una adaptación para que se pueda utilizar tanto con fechas formateadas como con el epoch time de unix y en castellano.

Para utilizarla, sería algo como esto:

echo nicetime('1988-11-14');
# Mostraría "Hace 21 años"
echo nicetime('2010-02-12');
# Mostraría "Dentro de 2 días"
echo nicetime('1234567890');
# Mostraría "Hace 1 año";

Esta es la función, y el ejemplo de resultado se puede ver a la derecha (en el globo azul de Twitter).

function nicetime($date){
   if(empty($date)){
      return "Fecha no especificada";
   }
   $periods    = array("segundo", "minuto", "hora", "día", "semana", "mese", "año", "década");
   $lengths    = array("60","60","24","7","4.35","12","10");

   $now            = time();
   if(is_int($date)){
      $unix_date   = $date;
   }else{
      $unix_date   = strtotime($date);
   }

   if(empty($unix_date)) {
      return "Fecha incorrecta";
   }
   if($now > $unix_date) {
      $difference  = $now - $unix_date;
      $tense       = "Hace ";
   }else{
      $difference  = $unix_date - $now;
      $tense       = "Dentro de ";
   }
   for($j = 0; $difference >= $lengths[$j] && $j < count($lengths)-1; $j++) {
      $difference /= $lengths[$j];
   }
   $difference = round($difference);
   if($difference != 1) {
      $periods[$j].= "s";
   }
   return "{$tense} $difference $periods[$j] ";
}

 

Nota 12 mayo 2010:

Parece que Alex Whinfield ha publicado un script parecido pero más sencillo, aunque lo que más me ha llamado la atención es uno de los comentarios en que le avisan de que wordpress incluye una función para esto llamada human_time_diff(), de manera que algunas veces no sería necesario incluir nuestra propia función 🙂



Josep Viciana

Programador de 28 años con una década de experiencia como programador. interesado en el diseño, ilustración y nuevas tecnologías. Dedicado desde siempre a la programación Web y desde hace algunos años también a la móvil.

3 comentarios

Tenía esta función por ahí guardada para cuando hiciera falta.
Hoy me la adapte y estaba haciendo unos test y veo que tiene un gran problema: sólo nos vale para fechas dentro del periodo de tiempo UNIX (1970-2038) de otro modo la fecha sera incorrecta.
Si tenemos esto en cuenta, funciona correctamente.
Saludos.

Hola Moisés. No tenía ni idea del efecto 2038, ni de la gravedad que puede suponer en general, ya no sólo en este método.

En cuanto al 1970, si no me equivoco, cuando llega al segundo 0 empezaría a contar numeros negativos no? creo que el error en realidad se daría a partir del 1902 para atrás, por el mismo motivo que el 2038 pero con signo negativo.

Gracias por el apunte, salud 😉

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *