8
votes

In Jekyll, I would like my home page to list the most recent posts grouped by date, like so:

September 6, 2013

  • Post 1
  • Post 2
  • Post 3

September 5, 2013

  • Post 1
  • Post 2

Basically, I just want to spit out a date heading when a post in the loop is from a different date from the one previously processed. I've tried to do this by testing if the next post in the for loop matches the date of the last post, and to display a date header only if it doesn't. This is what my Liquid template looks like:

---
layout: default
title: Home Page
---

{% assign thedate = '' %}

{% for post in site.posts %}

    {% if thedate != post.date | date: "%m-%d-%Y" %}
        <h2>{{ post.date | date: "%A, %B %e, %Y" }}</h2>
    {% endif %}

    {% assign thedate = post.date | date: "%m-%d-%Y" %}

    <h3 class="headline"><a href="{{ post.url }}">{{ post.title }}</a></h3>
    {{ post.content }}
    <hr>

{% endfor %}

If instead of using post.date | date: "%m-%d-%Y" I instead say simply post.date it works, and posts are grouped together, but only if the posts have the exact same date and time (not just the same day of the month). That's why I add the more specific post.date | date: "%m-%d-%Y".

Any ideas? Thanks so much for our help!!

3

3 Answers

6
votes

Found the answer by modifying the archives solution here: http://www.mitsake.net/2012/04/archives-in-jekyll/

Here is the code that works:

layout: default
title: Home Page
---

{% for post in site.posts %}

    {% capture day %}{{ post.date | date: '%m%d%Y' }}{% endcapture %}
    {% capture nday %}{{ post.next.date | date: '%m%d%Y' }}{% endcapture %}

    {% if day != nday %}
        <h5 class="date">{{ post.date | date: "%A, %B %e, %Y" }}</h5>
    {% endif %}
    {{ post.content }}
    <hr>

{% endfor %}
5
votes

These previous solutions are fantastic and elegant way to get around the shortcomings of previous versions of Jekyll but luckily in late 2016, Jekyll added a group_by_exp filter that can do this much more cleanly.

{% assign postsByDay = 
site.posts | group_by_exp:"post", "post.date | date: '%A, %B %e, %Y'" %}

{% for day in postsByDay %}
  <h1>{{ day.name }}</h1>
    <ul>
      {% for post in day.items %}
        <li><a href="{{ post.url }}">{{ post.title }}</a></li>
      {% endfor %}
    </ul>
{% endfor %}

Documentation can be found on the Jekyll Templates page.

4
votes

Alternative solution:

Directly capture the date in the format that you want to display at the end.
(here: %A, %B %d, %Y --> Monday, April 30, 2012)

Then you don't need to use | date: that often:

{% for post in site.posts %}
  {% capture currentdate %}{{post.date | date: "%A, %B %d, %Y"}}{% endcapture %}
  {% if currentdate != thedate %}
    <h2>{{ currentdate }}</h2>
    {% capture thedate %}{{currentdate}}{% endcapture %} 
  {% endif %}
    <h3><a href="{{ post.url }}">{{ post.title }}</a></h3>
{% endfor %}

The generated HTML:

<h2>Monday, April 30, 2012</h2>
<h3><a href="/2012/04/30/foo/">Foo</a></h3>
<h2>Friday, March 09, 2012</h2>
<h3><a href="/2012/03/09/bar/">Bar</a></h3>
<h3><a href="/2012/03/09/baz/">Baz</a></h3>