Note: This site is currently "Under construction". I'm migrating to a new version of my site building software. Lots of things are in a state of disrepair as a result (for example, footnote links aren't working). It's all part of the process of building in public. Most things should still be readable though.

Jekyll and GitHub Pages Liquid Date Formatting Examples

Code

TODO: Figure out why this isn't working in MDX



<</image-graphics/jekyll-logo-180x100.png|img>>

*Note: Since originally posting this, I have learned a better way to remove leading zeros is to use `{% raw %}{{ page.date | date: "%-m" }}{% endraw %}`. Note the dash in front of the "m". The examples haven't been updated yet. Either will work, but the new way is cleaner.*


###Summary (tl;dr)

The set of examples below provide tested code snippets for displaying several date formats on a Jekyll blog^1^^. They should also work on GitHub Pages, Shopify or anything else that uses Liquid. An alternate title for this post should be: 

*Everything you wanted to know about formatting dates in Jekyll but were afraid to ask.*<br /><br />

-- hr


###Overview

Jekyll^2</sup> (the simple, blog aware, static website generator) uses Shopify's Liquid Template Engine<sup>3</sup>. Displaying dates is done using the "`{{ "{{ page.date " }} }}`" supplied Liquid tag<sup>4^^. With no other alteration, the dates produced look something like:

    {{ page.date }}

If there are designs that use that format, they are few and far between. Creating friendlier looking dates is done by applying Liquid's "`date:`" filter. For example, the tag/filter combination:

    {% raw %}{{ page.date | date: '%B %d, %Y' }}{% endraw %}

produces more reader friendly dates like: 

    {{ page.date | date: '%B %d, %Y' }}

Much better, but depending on the date, subtle design issues show up. For example, during the first nine days of each month "leading zeros" crop up (e.g. "August 03, 2013" instead of "August 3, 2013"). Other gotchas with the basic Liquid filters include:

1. Adding a period behind the abbreviated month names has to be adjusted to handle May. For example, "Aug. 16, 2013" is fine. "May. 16, 2013" is not.
2. September is generally abbreviated "Sept." instead of Liquid's default "Sep."
3. To comply with the AP style guide the months April, May, June and July should not be abbreviated. Similar alterations are necessary to meet with the guidelines from the Chicago Manual of Style.

Most designs go with the available defaults. Either using a format that doesn't have these issues or, more frequently, letting the details slip. The information still gets across and every web site has a punch list of potential modifications that stretches to the horizon. So, I understand putting off finding a solution, but not having proper date formatting has always bugged me. While solving the issue for myself^5^^, I decided to put together this post as a public reference as well. I don't yet have the Ruby chops to contribute directly to Jekyll, but I can provide this reference to give back a little at least.

This set of Liquid date filters solves the issues listed above and explores a few other formatting options. Each one provides a solution for a specific display format and is provided with four output examples for the following date: 1) *May 3, 2013*, 2) *July 4, 2013*, 3) *September 23, 2013* and 4) *November 26, 2013*. These examples demonstrate if/how the various formatting issues are handled. After the examples, a few snippets of code for individual elements are provided. With these samples, just about any date format desired should be within easy reach. 


-- hr


###Liquid Date Formatting Examples for Jekyll


- **ISO 8601 Date**^5^^

      {% raw %}{{ page.date | date: "%Y-%m-%d" }}{% endraw %}

  Output Example 1: **2013-05-03**
  <br /> Output Example 2: **2013-07-04**
  <br /> Output Example 3: **2013-09-23**
  <br /> Output Example 4: **2013-11-26**

- **U.S. numeric style with four digit years** (With leading zeros.)

      {% raw %}{{ page.date | date: "%m/%d/%Y" }}{% endraw %}

  Output Example 1: **05/03/2013**
  <br />Output Example 2: **07/04/2013**
  <br />Output Example 3: **09/23/2013**
  <br />Output Example 4: **11/26/2013**

- **U.S. numeric style with four digit years** (Leading zeros removed.)

      {% raw %}
      <!-- Whitespace added for code readability -->
      {{ page.date | date: "%m" | plus:'0' }}
      /
      {{ page.date | date: "%d" | plus:'0' }}
      /
      {{ page.date | date: "%Y" }}
      {% endraw %}

  Output Example 1: **5/3/2013**
  <br />Output Example 2: **7/4/2013** 
  <br />Output Example 3: **9/23/2013**
  <br />Output Example 4: **11/26/2013**

- **U.S. numeric style with two digit year** (Leading zeros removed.)
    
      {% raw %}
      <!-- Whitespace added for code readability -->
      {{ page.date | date: "%m" | plus:'0' }}
      /
      {{ page.date | date: "%d" | plus:'0' }}
      /
      {{ page.date | date: "%y" }}
      {% endraw %}

  Output Example 1: **5/3/13**
  <br />Output Example 2: **7/4/13** 
  <br />Output Example 3: **9/23/13**
  <br />Output Example 4: **11/26/13**

- **Outside U.S. style with full month name** (Leading zeros removed.)
  
      {% raw %}{{ page.date | date: "%d" | plus:'0' }} {{ page.date | date: "%B %Y" }}{% endraw %}
  
  Output Example 1: **3 May 2013**
  <br />Output Example 2: **4 July 2013** 
  <br />Output Example 3: **23 September 2013**
  <br />Output Example 4: **26 November 2013**

- **U.S. style with full month name** (Leading zeros removed.)
  
      {% raw %}
      {{ page.date | date: "%B" }}
      {{ page.date | date: "%d" | plus:'0' }}, 
      {{ page.date | date: "%Y" }}
      {% endraw %}

  Output Example 1: **May 3, 2013**
  <br />Output Example 2: **July 4, 2013** 
  <br />Output Example 3: **September 23, 2013**
  <br />Output Example 4: **November 26, 2013**


- **U.S. style with full month names and ordinalized days** (Leading zeros removed.)

      {% raw %}
      <!-- Whitespace added for code readability -->
      {% assign d = page.date | date: "%d" | plus:'0' %}
      {{ page.date | date: "%B" }} 
      {% case d %}
        {% when 1 or 21 or 31 %}{{ d }}st
        {% when 2 or 22 %}{{ d }}nd
        {% when 3 or 23 %}{{ d }}rd
        {% else %}{{ d }}th
        {% endcase %}, 
      {{ page.date | date: "%Y" }}
      {% endraw %}

  Output Example 1: **May 3rd, 2013**
  <br />Output Example 2: **July 4th, 2013** 
  <br />Output Example 3: **September 23rd, 2013**
  <br />Output Example 4: **November 26th, 2013**

- **U.S. style with AP month abbreviations and ordinalized days** (Leading zeros removed.)

      {% raw %}
      <!-- Whitespace added for code readability -->
      {% assign d = page.date | date: "%d" | plus:'0' %} 
      {% assign m = page.date | date: "%B" %} 

      {% case m %}
        {% when 'April' or 'May' or 'June' or 'July' %}{{ m }}
        {% when 'September' %}Sept.
        {% else %}{{ page.date | date: "%b" }}.
        {% endcase %}
      {% case d %}
        {% when 1 or 21 or 31 %}{{ d }}st
        {% when 2 or 22 %}{{ d }}nd
        {% when 3 or 23 %}{{ d }}rd
        {% else %}{{ d }}th
        {% endcase %}, 
      {{ page.date | date: "%Y" }}
      {% endraw %}

  Output Example 1: **May 3rd, 2013**
  <br />Output Example 2: **July 4th, 2013** 
  <br />Output Example 3: **Sept. 23rd, 2013**
  <br />Output Example 4: **Nov. 26th, 2013**


- **U.S. style full day and full month names** (Leading zeros removed.)

      {% raw %}
      {{ page.date | date: "%A, %B" }} 
      {{ page.date | date: "%d" | plus:'0' }}, 
      {{ page.date | date: "%Y" }}
      {% endraw %}

  Output Example 1: **Friday, May 3, 2013**
  <br />Output Example 2: **Thursday, July 4, 2013** 
  <br />Output Example 3: **Monday, September 23, 2013**
  <br />Output Example 4: **Tuesday, November 26, 2013**

- **Chicago Manual of Style day abbreviations and U.S. style date** (With "Thurs." and "Tues.")

      {% raw %}
      <!-- Whitespace added for code readability -->
      {% assign dy = page.date | date: "%a" %}
      {% case dy %}
        {% when "Tue" %}Tues
        {% when "Thu" %}Thurs
        {% else %}{{ dy }}
        {% endcase %}. 
      ~
      {{ page.date | date: "%B" }} 
      {{ page.date | date: "%d" | plus:'0' }}, 
      {{ page.date | date: "%Y" }}
      {% endraw %}

  Output Example 1: **Fri. ~ May 3, 2013**
  <br />Output Example 2: **Thurs. ~ July 4, 2013** 
  <br />Output Example 3: **Mon. ~ September 23, 2013**
  <br />Output Example 4: **Tues. ~ November 26, 2013**


###Individual Component Snippets for Liquid Date Formatting

These individual snippets are for a few of the tricker formatting filters. Some that weren't used in the examples above. For those interested in the approach, the hack I'm using to remove leading zeros is to add "0" to the string. This turns the string into an integer. When the integer is rendered back as a string the leading zero disappears. Hurray for dynamic typing. 

- **Numeric month with leading zeros removed**

      {% raw %}
      {{ page.date | date: "%m" | plus:'0' }}
      {% endraw %}

- **Numeric day with leading zeros removed**

      {% raw %}
      {{ page.date | date: "%d" | plus:'0' }}
      {% endraw %}

- **Ordinalized numeric day with leading zeros removed**

      {% raw %}
      {% assign d = page.date | date: "%d" | plus:'0' %}
      {% case d %}
        {% when 1 or 21 or 31 %}{{ d }}st
        {% when 2 or 22 %}{{ d }}nd
        {% when 3 or 23 %}{{ d }}rd
        {% else %}{{ d }}th
        {% endcase %}
      {% endraw %}

- **AP Style month abbreviations**

      {% raw %}
      {% assign m = page.date | date: "%B" %}
      {% case m %}
        {% when 'April' or 'May' or 'June' or 'July' %}{{ m }}
        {% when 'September' %}Sept.
        {% else %}{{ page.date | date: "%b" }}.
        {% endcase %}
      {% endraw %}

    (Produces: "Jan.", "Feb.", "Mar.", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec.")

- **Chicago Manual of Style day abbreviations**

      {% raw %}
      {% assign dy = page.date | date: "%a" %}
      {% case dy %}
        {% when "Tue" %}Tues
        {% when "Thu" %}Thurs
        {% else %}{{ dy }}
        {% endcase %}.
      {% endraw %}

    (Produces: "Sun.", "Mon.", "Tues.", "Wed.", "Thurs.", "Fri.", "Sat.")

- **Chicago Manual of Style month abbreviations**

      {% raw %}
      {% assign m = page.date | date: "%B" %}
      {% case m %}
        {% when 'May' or June' or 'July' %}{{ m }}
        {% when 'September' %}Sept.
        {% else %}{{ page.date | date: "%b" }}.
        {% endcase %}
      {% endraw %}

    (Produces: "Jan.", "Feb.", "Mar.", "Apr.", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec.")

With that, you should be in pretty good shape. If you can't directly create what you need from the above samples or snippets you should at least be able to use a similar approach to piece together what you need. 


-- hr


*Notes on the Examples*

1. The hour, minute and second parts of the full date/time stamp aren't being used because Jekyll tends to zero them out. 
2. In some of the examples, the code is split to multiple lines to help readability. If it's a natural break point where white space already exists, this won't effect HTML rendering. In some cases, it will introduce unwanted white space. Simply move everything back to one line to create the desired presentation.


*Footnotes*

1. These examples were create on a Mac running OS X 10.8.5 with: Ruby 2.0.0p247 - Jekyll 1.2.1 - liquid 2.5.2. Your mileage may vary.
2. The main <<link|Jekyll website](http://jekyllrb.com/) provides a great overview of the software. You can learn even more with a visit to the [Jekyll's GitHub Repo|https://github.com/mojombo/jekyll>>.
3. <<link|Shopify's Liquid template engine|http://wiki.shopify.com/Liquid>>. "A small and fast template language which is quick to learn but very powerful for full customization."
4. The Liquid Date Filter <<link|offers some basic formatting elements|http://wiki.shopify.com/Date>> and is the basis of these code snippets. Note that in some cases "post.date" might be required instead of "page.date".
5. Observant readers will notice that as of the time this post went live, my design still uses a date format with leading zeros. I have the solution, it just hasn't been implement yet. It'll go in with the next set of design changes. 
6. <<link|ISO 8601](http://en.wikipedia.org/wiki/ISO_8601) - "Data elements and interchange formats - Information interchange - Representation of dates and times is an international standard covering the exchange of date and time-related data." A perfect example of how Time really is [wibbly wobbly timey wimey... stuff|http://www.youtube.com/watch?v=vY_Ry8J_jdw>>.