JMiur [E]

Las fechas relativas son algo que se puso de moda hace ya tiempo y que vemos mucho en las redes sociales.

Una fecha relativa, en lugar de mostrar dia, mes y año de cierta entrada, lo que indica es el tiempo transcurrido desde su publicación hasta el momento actual; por ejemplo: "hace 2 minutos" o "dos dias atrás" o "hace un año"; cualquier texto que a uno se le ocurra.

Quienes usan Wordpress disponen de muchos plugins ya pensados para eso (la mayoría en inglés, of course) pero, en Blogger no es algo que se vea muy seguido. En Blog and Web hay una explicación de cómo hacerlo en este tipo de blogs y se trata de una adaptación de, justamente, un plugin de WordPress. Basándome en eso, vamos a ver si se pueden generar otras posibilidades.

Lo primero que pienso es que, para que este tipo de cosas funcione correctamente lo que debo usar es una fecha perfecta ¿A qué me refiero? A que JavaSprit posee muchas funciones para manejar fechas pero si quiero hacer un cálculo preciso, necesito un formato de fecha de esos que, a primera vista, es completamente ilegible así que no puedo usar ni <data:post.dateHeader/> ni <data:post.timestamp/> que son los dos datos que puedo configurar, tanto en el blog como en el widget de las entradas; necesito otro que no usamos nunca pero que está allí y se llama: <data:post.timestampISO8601/>

Ese dato me dará como resultado una fecha de este tipo:

2010-03-25T15:30:20-03:00

¿Que es eso? El año, el mes, el dia; seguido de la letra T que indica la hora, los minutos y los segundos, seguido de un valor (-03:00 en mi caso) que es la Zona Horaria establecida en Configuración | Formato.


Lo voy a usar pro dos razones, primero, porque manejar fechas en JavaScript que no están en inglés resulta complicado y segundo, porque de ese modo, no necesito modificar nada de la configuración del blog. Entonces, debería crear una función que lea ese dato y lo convierta en un número.

Suponiendo que la variable dato contenga esa fecha :
// la fecha y hora de publicación del post, expresada en segundos
var fechapost = new Date(dato).getTime()/1000;

// la fecha y hora actual expresada en segundos
var ahora = new Date().getTime()/1000;

// si la fecha es mayor que "ahora" es un post con fecha futura así que debería hacer algo distinto o no hacer nada
if(fechapost>ahora) { return; }

// estos son los segundos transcurridos entre el momento actual y el momento en que se publicó el post
var segundos = ahora - fechapost;
Teniendo el valor de los segundos, ahora es cuestión de usar aritmética para calcular las fracciones es decir, expresar segundos de otra manera. La solución clásica es algo así:
var calctiempo = segundos;
var salida = "";
var bucle = 6;
var t;

var p = [];
p['año'] = 31536000;
p['semana'] = 604800;
p['dia'] = 86400;
p['hora'] = 3600;
p['minuto'] = 60;
p['segundo'] = 1;

for(var periodo in p) {
  var valor = p[periodo];
  if(calctiempo>=valor) {
    t = Math.floor(calctiempo/valor);
    calctiempo%=valor;
    salida += t; // es el valor
    salida += " "; // un caracter espacio
    salida += periodo; // el texto 
    if(t>1){ salida += "s"; } // los plurales
  }
  salida += " "; // otro caracter espacio
  bucle--;
  if(bucle==0){ break; }
}

document.write(salida);
Esto mostraría algo así:

2 dias 17 horas 59 minutos 10 segundos

Ahora bien, sería mejor usar algo menos matemático y poner textos más humanos, ya sea "hace instantes", "hace más de un hora" o "hace tanto tiempo que ya no me acuerdo". Para eso puede usarse el mismo tipo de esquema que utilizan los scripts de Twitter así me voy a crear una función similar donde, usando aritmética, podamos ir estableciendo fracciones de tiempo a gusto de cada uno; nada grave, por ejemplo:

minutos = segundos / 60
horas = segundos / 60*60 = segundos / 3600
dias = segundos / 60*60*24 = segundos / 86400
semanas = segundos / 60*60*24*7 = segundos / 604800

Los meses ya son complicados de calcular así que voy por lo fácil, hago de cuenta que todos tienen 31 dias y a otra cosa:

meses = segundos / 60*60*24*31 = segundos / 2678400

Algo similar pasaría con los años bisiestos pero acá no se trata de precisión sino de redondeos así que:

años = segundos / 60*60*24*365 = segundos / 31536000

La función que pongo antes de </head>
<script type='text/javascript'>
//<![CDATA[
function fecharelativa(dato) {
  var fechapost = new Date(dato).getTime()/1000; // fecha y hora de la publicación
  var ahora = new Date().getTime()/1000; // fecha y hora actual
  if(fechapost>ahora) { return; } // si la fecha es incongruente no hago nada
  // los segundos transcurridos entre esas dos fechas
  var segundos = ahora - fechapost;

  // calculo toods los datos
  var minutos = (parseInt(segundos / 60)).toString();
  var horas = (parseInt(segundos / 3600)).toString();
  var dias = (parseInt(segundos / 86400)).toString();
  var semanas = (parseInt(segundos / 604800)).toString();
  var meses = (parseInt(segundos / 2678400)).toString();
  var anios = (parseInt(segundos / 31536000)).toString();
  
  // y comienzo a armar lo que será el texto teneindo en cuenta que debo redondear ciertas fracciones
  var salida = "";

  if (minutos < 1) { // menos de un minuto
    salida = "hace menos de un minuto";
  } else if(minutos == 1) { // un minuto y algo más, menos de dos minutos
    salida = "hace poco más de un minuto";
  } else if(horas < 1) { // menos de una hora
    salida = "hace " + minutos + " minutos";
  } else if(horas == 1) { // una hora y algo más, menos de dos horas
    salida = "hace poco más de una hora";
  } else if(dias < 1) { // menos de un dia
    salida = "hace " + horas + " horas";
  } else if(dias == 1) { // un dia y algo más, menos de dos dias
    salida = "hace poco más de un dia";
  } else if(semanas < 1) { // menos de una semana
    salida = "hace menos de una semana";
  } else if(semanas == 1) { // una semana y algo más, menos de dos semanas
    salida = "hace una semana";
  } else if(meses < 1) { // aproximadamente menos de un mes
    salida = "hace " + dias + " días";
  } else if(meses == 1) { // un mes ... con un cierto margen
    salida = "hace un mes";
  } else if(anios < 1) { // menos de un año
    salida = "hace " + meses + " meses";
  } else if(anios == 1) { // aproximadamente un año
    salida = "hace un año";
  } else { // más de un año
    salida = "hace " + anios + " años";
  }

  // y escribo ese texto
  document.write(salida);
}
//]]>
</script>
¿Cómo lo uso en Blogger? Tengo que llamar a al función en alguna parte; por ejemplo, podría hacerlo en el mismo lugar donde coloco el nombre del autor; busco <data:post.author/> y lo cambio así:

Publicado por <data:post.author/>
<script type='text/javascript'>fecharelativa(&#39;<data:post.timestampISO8601/>&#39;);</script>

Como no voy a usar este esquema de fechas de entradas, no hay un ejemplo pero, no sólo es posible utilizarlo para mostrar la fecha de las entradas, también podríamos usarlo para mostrar la fecha de los comentarios que suele ser uno de esos datos que uno no personaliza y en el que solemos ver la hora.

Para esto, el script es exactamente el mismo pero, debo ir a Configuración | Comentarios y establecer un formato de fecha adecuado; en este caso, elijo este que es el más completo:


Luego, debo llamar a la función así que busco esta parte:
<dd class='comment-footer'>
  <span class='comment-timestamp'>
    <a expr:href='&quot;#comment-&quot; + data:comment.id' rel='nofollow' title='comment permalink'><data:comment.timestamp/></a>
    <b:include data='comment' name='commentDeleteIcon'/>
  </span>
</dd>
Y hago lo mismo que antes, cambio <data:comment.timestamp/> por el script:
<script type="text/javascript">fecharelativa(&#39;<data:comment.timestamp/>&#39;);</script>

ACTUALIZACION:

Como Blogger parece haber cambaido las opciones de formato y las fechas que antes se mostraban como:
7/17/2011 00:30:00 AM o 7/17/2011 00:30:00 PM
ahora se muestran como:
7/17/2011 00:30:00 a.m. o 7/17/2011 00:30:00 p.m.
debería modificar el inico del script para que puedan ser interpretadas y la funcion debería comenzar así:
dato=dato.replace("a.m.","AM");
dato=dato.replace("p.m.","PM");
var fechapost = new Date(dato).getTime()/1000; // fecha y hora de la publicación

27 comentarios:

MyM  

!Mammmaaa Mía! Admiro tu inteligencia y dedicación. Un gusto pasar JM.

Responder
Unknown  

Uff gracias por compartirlo:D. No muchos bloggers se atreven a compartir los detalles de programación(incluyéndome jeje).

Gracias JMiur!

PD: no se si creas pertinente pasar a mi blog y ver la nueva interfaz de blogger haber que te parece, yo la veo igual a Google+

Responder
Unknown  

Por cierto JMiur, me quede un rato mirando tu código y tienes dos variables mal en tu script final:

} else if(mes < 1) { // aproximadamente menos de un mes
salida = "hace " + dias + " días";
} else if(mes == 1) { // un mes ... con un cierto margen
salida = "hace un mes";

En realidad es una sola, aparece dos veces:P, creo que debería ser:

} else if(meses < 1) { // aproximadamente menos de un mes
salida = "hace " + dias + " días";
} else if(meses == 1) { // un mes ... con un cierto margen
salida = "hace un mes";

Error insignificante, a todos nos pasa, saludos!

Responder
Felipe Calvo Cepeda  

Siempre me ha dado "perecita" habilitar el display de la fecha de publicación, pero me estas tentando y de que manera.
Gracias totales por compartir tus ideas y conocimientos, de verdad que si. :D

Responder
Bonzu Pipinpadaloxicopolis III  

Ni tardo ni perezoso JMiur en implementarlo :D

Responder
egoloco  

Ajá! Bueno. No me queda. No se qué estoy haciendo mal. Cuando intento modificar el enlace con el script el enlace desaparece. Sugerencias?

Responder
JMiur  

Tendría que ver tu ejemplo para poder decirte algo.

Responder
egoloco  

El ejemplo esta en este blog. Una entrada con comentarios es esta: ENLACE

Responder
JMiur  

En la funcion faltaría la llave de cierre:

document.write(salida);
}
//]]>
</script>

Responder
egoloco  

Correctisimo JMiur. Creí que estaba ubicando mal las cosas. Una llave... Gracias!

Responder
JMiur  

Me parece que algo salió mal publicado en la entrada o yo me equivóque al transcribir porque la llave no se veía y n opodía copairse. Ahí lo arreglé .. .espero :D

Responder
egoloco  

Somos humanos, a cualquiera le puede pasar. Pudo haber sido una imprudencia mia o tuya. :D

Responder
JMiur  

No, no, no. hay que echarle la culpa a Blogger. Nosotros somos perfectisimos :-)

Responder
el Zambullista  

Hola, JMiur.
Una consulta: ¿podrían cambiarse las fechas relativas de una lista de blogs por fechas absolutas? Supongo que debería cambiar esta parte de la plantilla, donde está el elemento (quité las llaves de los tags para no tener problemas con el formulario):

b:if cond='data:showTimePeriodSinceLastUpdate == "true"'
div class='item-time'
data:item.timePeriodSinceLastUpdate/
/div
/b:if

Pero los intentos que hice no funcionaron.
Gracias de antemano, y saludos.

Responder
JMiur  

Pués no veo forma práctica de hacer eso. Habría que comocer todas las variantes posibles en que se muestra e interpretar cada uno de eso textos para extraer los valores. Demasiado complejo.

Responder
Felipe Calvo Cepeda  

Listo, funcionando de mil maravillas en los comentarios ^^
Gracias de nuevo JMiur.

Responder
JMiur  

Perfecto, Felipe :D

Responder
egoloco  

Si quiero que la palabra "años" lleve la Ñ cómo debo hacer? He probado con &#237; pero no sale

Responder
JMiur  

En una página normal donde el juego de caracterees es UTF-8, simplemente usando la ñ; no requiere nada más.

Responder
egoloco  

Era más fácil de lo que pensé. :-| Gracias.

Responder
Ismail Sosse Alaoui  

Hi, admin
I think this hack doesn't work good, you can do a test and see, you drop a comment, the operation last at least 1 minute, but time that show this hack 3 months ago, i think that you should correct it
thanks to answer

Responder
Ismail Sosse Alaoui  

excuse me,i found the problem, after fixing formating it works good thanks

Responder
egoloco  

Hace tiempo tenía una duda, no estoy seguro si te la plantié, pero... cuando en mi blog hago un comentario, dicho comentario muestra la hora como "hace 30 días" siendo que comenté hace 30 segundos... Soy yo que está mal? Blogger talvez?

Y si hago lo de los Comentarios anidados y replys se modifica esto de la fecha y hora en los mismos?

JMiur  

Primero que nada, verifica que la Zona Horaria de la configuración sde Blogger sea la correcta.

egoloco  

Después de comentar vi sobre el final del post la Actualización que hiciste y me sirvió. Era la hora, porque en la Zona Horaria puse Montevideo y faltaban las tres líneas de script que pusiste. Gracias JMiur!

Responder
Llusan  

En su script usa la zona horaria de GMT-03:00, pero, al momento de pedir la fecha/hora actual en mi PC (con GMT-05:00) ---> new Date().getTime() ; este dará el desfase de dos horas...

JMiur  

No. El script no establece nada de eso. Toma el dato que genera Blogger que es el que hayas definido en la Configurción del blog. La variable dato es ese valor; cualquiera sea.

var fechapost = new Date(dato).getTime()/1000;

Responder

¿Quiere dejar un comentario?

recuerde que los comentarios están siendo moderados y serán publicados a la brevedad ...

Nota: sólo los miembros de este blog pueden publicar comentarios.

Si le gusta ir a lo seguro utilice este botón para abrir los comentarios en una ventana modal en esta misma pagina.

Si añora tiempos idos, use este enlace para agregar un comentario al viejo estilo ...

 
CERRAR