Trabajando con fechas en Jekyll

10 minuto(s) de lectura

Si acudimos al repositorio en GitHub asociado al tema Hooligan para Jekyll, apreciaremos un par de diferencias, con respecto a este sitio web, acerca de cómo se gestiona el tratamiento de las fechas. En primer lugar, si centramos nuestra atención en la página de bienvenida, dentro del apartado correspondiente al listado de entradas en el blog, la fecha aparece como “29 Dec 2011”:

Fecha en página de bienvenida

Es decir, el día va seguido por la abreviatura en inglés del mes, cerrando la fecha la expresión del año con cuatro dígitos. No me terminaba de convencer el detalle de que en una página en español las fechas se mostrasen en otro idioma, por lo que, apoyándome en esta fantástica guía, modifiqué la parte del código asociada al mencionado comportamiento. De esta manera, ahora, en la página de bienvenida de este sitio web, los elementos que conforman las fechas son todos numéricos y están separados mediante el símbolo /.

Veamos cómo podemos conseguir tal efecto en particular, y luego, gracias a la comentada guía, cada uno podrá modificar el formato de la fecha a su antojo. Utilizando nuestro de editor de texto plano favorito, abrimos el archivo index.md, que se encuentra en la raíz del directorio donde tengamos ubicado nuestro sitio web. Aproximadamente hacia el final del mismo, encontraremos el siguiente bloque de código:

<ul class="posts">
  {% for post in site.posts %}
    <li><span>{{ post.date | date_to_string }}</span> &raquo; <a href="{{ BASE_PATH }}{{ post.url }}">{{ post.title }}</a></li>
  {% endfor %}
</ul>

Ahora, simplemente tenemos que sustituir date_to_string por date: "%d/%m/%Y", tal y como nos indican en la guía referida arriba. Esto provocará que fechas del estilo “29 Dec 2011” se transformen automáticamente en “29/12/2011”, suprimiendo así esa parte en inglés que desentonaba bastante en una página web en español. Por otro lado, como el tipo de letra escogido para los párrafos no es monoespaciado, a la hora de generar un listado de artículos existe un pequeño “baile” en las distintas líneas, ya que unas fechas ocupan más espacio horizontal que otras. Para solucionar este hecho, podemos declarar el atributo style="font-family:monospace" para la etiqueta <span> que envuelve la fecha en sí. Por último, como mostrar en la página de bienvenida del sitio web un listado completo de los artículos del blog me parecía un tanto excesivo, he limitado esta operación a las diez entradas más recientes, acción que podemos conseguir insertando limit:10 en la cabecera de definición del bucle for.

El siguiente bloque de código recoge todas las modificaciones nombradas en el párrafo anterior y es el que figura en el archivo index.md que aparece en el directorio raíz de mi sitio web:

<ul class="posts">
  {% for post in site.posts limit:10 %}
    <li><span style="font-family:monospace">{{ post.date | date: "%d/%m/%Y" }}</span> &raquo; <a href="{{ BASE_PATH }}{{ post.url }}">{{ post.title }}</a></li>
  {% endfor %}
</ul>

Visitemos ahora la sección de la página denominada Archive, donde aparece el listado de todos los posts de un sitio web desglosados por año y mes, tal y como figura en la siguiente imagen:

Fecha en página de bienvenida

La idea me pareció bastante atractiva, pero saltan a la vista dos posibles detalles sobre los que tendremos que trabajar:

  • El formato de las fechas es bastante similar al que aparece en la página de bienvenida, por lo que tendremos que seguir pasos parecidos a los descritos en párrafos anteriores para modificar este comportamiento.
  • Los meses vienen dados por su nombre completo en inglés, cuando lo ideal sería que apareciesen en español. Esto nos va a suponer un esfuerzo extra, aunque tampoco la variación será excesivamente complicada.

Empecemos revisando el código fuente de archive.html, fichero que no aparece en mi repositorio, ya que lo renombré a blog.html (desafotunada acción que ya comenté en su momento en un artículo anterior de la serie). El código es ciertamente escueto:

---
layout: page
title : Archive
header : Post Archive
group: navigation
---
{% include JB/setup %}

{% assign posts_collate = site.posts %}
{% include JB/posts_collate %}

Tras la declaración de la cabecera del archivo, que se encuentra encerrada entre los símbolos ---, se incluye el código de configuración de la estructura de los enlaces del sitio web, que reside en la carpeta _includes\JB\, en el interior del archivo setup. Esta línea será común a todos los posts y páginas que creemos para nuestro sitio web, y aparecerá siempre a continuación de la cabecera. A continuación, se almacenan los posts en la variable posts_collate, para incluir, acto seguido, el código que se encuentra en el fichero posts_collate, ubicado en el directorio _includes\JB\. Echemos un vistazo a su contenido:

{% comment %}<!--
Collate_posts helper. Collated posts by year and month.
Usage:
  1) assign the 'posts_collate' variable to a valid array of posts.
  2) include JB/posts_collate
  example:
    {% assign posts_collate = site.posts %}
    {% include JB/posts_collate %}

  Ordering:
    Posts are displayed in reverse chronological order.
    For normal chronological order:
      1) Change the for loop to this:
        => 'for post in site.posts reversed'
      2) Next make sure to change 'post.previous.date' to:
        => 'post.next.date'
        
-->{% endcomment %}

{% if site.JB.posts_collate.provider == "custom" %}
  {% include custom/posts_collate %}
{% else %}
  {% for post in posts_collate  %}
    {% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
    {% capture this_month %}{{ post.date | date: "%B" }}{% endcapture %}
    {% capture next_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %}
    {% capture next_month %}{{ post.previous.date | date: "%B" }}{% endcapture %}
  
    {% if forloop.first %}
      <h2>{{this_year}}</h2>
      <h3>{{this_month}}</h3>
      <ul>
    {% endif %}
  
    <li><span>{{ post.date | date: "%B %e, %Y" }}</span> &raquo; <a href="{{ BASE_PATH }}{{ post.url }}">{{ post.title }}</a></li>
  
    {% if forloop.last %}
      </ul>
    {% else %}
      {% if this_year != next_year %}
        </ul>
        <h2>{{next_year}}</h2>
        <h3>{{next_month}}</h3>
        <ul>
      {% else %}    
        {% if this_month != next_month %}
          </ul>
          <h3>{{next_month}}</h3>
          <ul>
        {% endif %}
      {% endif %}
    {% endif %}
  {% endfor %}
{% endif %}
{% assign posts_collate = nil %}

Es posible que, a primera vista, el anterior bloque de código intimide bastante. Sin embargo, si nos detenemos unos instantes a estudiar su estructura, aproximadamente el primer tercio del mismo está compuesto por un comentario que explica ciertos detalles sobre su funcionamiento; el tercio final declara la lógica que permite separar tanto los años como los meses; y la parte central está dedicada a almacenar los valores de ciertas variables de interés. Es precisamente en dicha sección central donde introduciremos nuestras modificaciones para que el formato de las fechas se adapte, de manera más agradable, al castellano.

Empecemos por la parte sencilla, aquella asociada a cómo se muestran las fechas precediendo los enlaces de todos y cada uno de los posts, que es la comprendida entre las etiquetas <li> y </li>, y donde modificaremos el código ubicado entre <span> y </span>. En primer lugar, cambiaremos date: "%B %e, %Y" (que es lo que provoca que las fechas aparezcan como “December 29, 2011”) por date: "%d/%m/%Y", para que el formato sea idéntico al que declaramos en la página de bienvenida del sitio web. En segundo lugar, definiremos como atributo para la etiqueta <span> un tipo de fuente monoespaciado, para así evitar la aparición del ya comentado “baile” horizontal en las distintas líneas.

Pasemos ahora a la parte más “jugosa”, aquella que respecta a variar el encabezado de la separación por meses. En el código apreciamos dos líneas que recogen tanto para el post actual, como para el previo, el mes en el que fue publicado:

{% capture this_month %}{{ post.date | date: "%B" }}{% endcapture %}    
{% capture next_month %}{{ post.previous.date | date: "%B" }}{% endcapture %}

Utilizando %B conseguimos que el mes se muestre con su nombre completo, pero en inglés. La filosofía que seguiremos para modificar el anterior comportamiento será la siguiente:

  • Registraremos (y almacenaremos en cierta variable) el valor numérico del mes en el que un artículo se publicó.
  • En función del valor que tome dicha variable, utilizando un bloque de casos, le asignaremos el nombre completo en español del mes correspondiente.

Por ejemplo, para la primera línea del par mostrado arriba, lo que haremos será sustituir:

{% capture this_month %}{{ post.date | date: "%B" }}{% endcapture %}    

por

{% capture this_month %}
  {% assign this_month = post.date | date: "%m" %}	
  {% case this_month %} 
	{% when '1' %}Enero
	{% when '2' %}Febrero
	{% when '3' %}Marzo
	{% when '4' %}Abril
	{% when '5' %}Mayo
	{% when '6' %}Junio
	{% when '7' %}Julio
	{% when '8' %}Agosto
	{% when '9' %}Septiembre
	{% when '10' %}Octubre
	{% when '11' %}Noviembre
	{% when '12' %}Diciembre
  {% endcase %}
{% endcapture %}

Mientras que en lugar de

{% capture next_month %}{{ post.previous.date | date: "%B" }}{% endcapture %}

teclearemos

{% capture next_month %}
  {% assign next_month = post.previous.date | date: "%m" %}	
  {% case next_month %} 
	{% when '1' %}Enero
	{% when '2' %}Febrero
	{% when '3' %}Marzo
	{% when '4' %}Abril
	{% when '5' %}Mayo
	{% when '6' %}Junio
	{% when '7' %}Julio
	{% when '8' %}Agosto
	{% when '9' %}Septiembre
	{% when '10' %}Octubre
	{% when '11' %}Noviembre
	{% when '12' %}Diciembre
  {% endcase %}
{% endcapture %}

De esta manera, conseguiremos un resultado como el que puede apreciarse en la página blog de este sitio web. Si bien es cierto que este tipo de configuraciones se pueden llevar a cabo de forma más sencilla a través del uso de plugins, como estamos hospedando la página en GitHub Pages hemos de buscar, en la medida de lo posible, soluciones en puro Liquid para resolver cualquier inconveniente con el que nos topemos.

Para finalizar este artículo, comparto el código completo del archivo posts_collate que, a día de hoy, genera en mi sitio web el listado de entradas que compone la página asociada al blog.

{% comment %}<!--
Collate_posts helper. Collated posts by year and month.
Usage:
  1) assign the 'posts_collate' variable to a valid array of posts.
  2) include JB/posts_collate
  example:
    {% assign posts_collate = site.posts %}
    {% include JB/posts_collate %}

  Ordering:
    Posts are displayed in reverse chronological order.
    For normal chronological order:
      1) Change the for loop to this:
        => 'for post in site.posts reversed'
      2) Next make sure to change 'post.previous.date' to:
        => 'post.next.date'
        
-->{% endcomment %}

{% if site.JB.posts_collate.provider == "custom" %}
  {% include custom/posts_collate %}
{% else %}
  {% for post in posts_collate  %}
    {% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}	
	{% capture this_month %}
	{% assign this_month = post.date | date: "%m" %}	
	{% case this_month %} 
		{% when '1' %}Enero
		{% when '2' %}Febrero
		{% when '3' %}Marzo
		{% when '4' %}Abril
		{% when '5' %}Mayo
		{% when '6' %}Junio
		{% when '7' %}Julio
		{% when '8' %}Agosto
		{% when '9' %}Septiembre
		{% when '10' %}Octubre
		{% when '11' %}Noviembre
		{% when '12' %}Diciembre
	{% endcase %}
	{% endcapture %}	
	{% capture next_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %}	    
	{% capture next_month %}
	{% assign next_month = post.previous.date | date: "%m" %}	
	{% case next_month %} 
		{% when '1' %}Enero
		{% when '2' %}Febrero
		{% when '3' %}Marzo
		{% when '4' %}Abril
		{% when '5' %}Mayo
		{% when '6' %}Junio
		{% when '7' %}Julio
		{% when '8' %}Agosto
		{% when '9' %}Septiembre
		{% when '10' %}Octubre
		{% when '11' %}Noviembre
		{% when '12' %}Diciembre
	{% endcase %}
	{% endcapture %}	
    {% if forloop.first %}
      <h2>{{this_year}}</h2>
      <h3>{{this_month}}</h3>
      <ul>
    {% endif %}
  
    <li><span style="font-family:monospace">{{ post.date | date: "%d/%m/%Y" }}</span> &raquo; <a href="{{ BASE_PATH }}{{ post.url }}">{{ post.title }}</a></li>
  
    {% if forloop.last %}
      </ul>
    {% else %}
      {% if this_year != next_year %}
        </ul>
        <h2>{{next_year}}</h2>
        <h3>{{next_month}}</h3>
        <ul>
      {% else %}    
        {% if this_month != next_month %}
          </ul>
          <h3>{{next_month}}</h3>
          <ul>
        {% endif %}
      {% endif %}
    {% endif %}
  {% endfor %}
{% endif %}
{% assign posts_collate = nil %}

Nota (I): aunque el presente artículo está fuertemente centrado en las particularidades del tema Hooligan, las ideas expuestas a lo largo de los anteriores párrafos, de cara a la modificación del formato en el que se muestran las fechas, pueden extrapolarse sin problema alguno a temas alternativos. La única complicación que puede surgir reside en localizar, de manera acertada, el fichero donde se encuentra el código que declara la configuración del comportamiento de date.

Nota (II): esta entrada se ha almacenado dentro del proyecto MetaBlog, quedando así disponible para su consulta también a través del siguiente enlace.

Comentar