2

I am trying to list the months (January, Febuary etc) between two dates. I have a start date: 5/4/2015 and an end date: 9/25/2015.

Using range I am able to return the month numbers, but just can't figure out the correct syntax to convert 5 into May.

Here's what I've got so far, maybe there is a better way all together?

TWIG

{% set startMonth = craft.plugin.getStartDate() %} // returns 5/4/2015
{% set endMonth = craft.plugin.getEndData() %} // returns 9/25/2015

{% for month in range(startMonth, endMonth, 1) %}
    {{ month }}  // returns 5 6 7 8 9
{% endfor %}

I've tried doing something like: {{ month|date('F') }} but that returns December for each result.

I'll eventually need days within this month range, but I am hoping from this I can figure that out.

1
  • Thank you everyone - these are all so great. I wish there was a way to accept all answers!
    – Damon
    Commented May 7, 2015 at 13:40

4 Answers 4

3

I made a Craft plugin that simply wraps PHP DatePeriod: "Date Period plugin for Craft". The plugin provides a datePeriod Twig function. It works really simple, your give it a start date, an end date and an interval to create a DatePeriod object.

datePeriod( startDate, endDate, interval )

This DatePeriod object you can now iterate over to get the dates, recurring at the set interval, over the period spanning your start and end date. By default the interval is set to 1 day, but you can modify that with the (optional) parameter.

{% set datePeriod = datePeriod(startDate, endDate, '1 month') %}

{% for month in datePeriod %}
    {{ month|date('F') }}
{% endfor %}

To also list the days in between, you would add Craft's group filter like so:

{% set datePeriod = datePeriod(startDate, endDate) %}

{% for month, daysInMonth in datePeriod|group('{ object|date("F") }') %}
    {{ month }}
    {% for day in daysInMonth %}
        {{ day|date('d') }}
    {% endfor %}
{% endfor %}
2

Ok, there must be a better way, but if you want to also show the days eventually, try this approach (As hinted by this answer, you basically loop through the seconds, in steps of 86400 (= one day)):

{% set start = craft.plugin.getStartDate() %} // returns 5/4/2015
{% set end = craft.plugin.getEndData() %} // returns 9/25/2015

{% set currentMonth = null %}
{% for day in range(start | date('U'), end | date('U'), 86400) %}
    {% set month = day | date('F') %} {# create a month variable #}
    {% if month != currentMonth %}
        {{ month }} {# display the month, once #}
        {% set currentMonth = month %}
    {% endif %}

    {{ day | date('d') }} {# display the day #}
{% endfor %}
1
  • Ah - I had looked at the thread you linked to - this is where I was going wrong: {% if month != currentMonth %}...{%endif%}
    – Damon
    Commented May 7, 2015 at 13:41
2

You could solve this with a recursive macro and add a day / month to the startDate with each iteration:

{% macro listDays(startDate, endDate) %}
    {% import _self as self %}

    {% if startDate <= endDate %}
        {{ startDate|date('F-d') }}
        {{ self.listDays(startDate|date_modify('+ 1 day'), endDate) }}
    {% endif %}

{% endmacro %}

And then call it like so:

{{ macros.listDays(startDate, endDate) }}
2

I have this macro in my _macros/_utils.html:

{% macro monthNameFromNumber(monthNumber) %}
  {# monthNumber will be 00-12. we use that to construct a date string,
     convert it to date and then pick the month name out of that #}
  {{ date('2014-' ~ monthNumber ~ '-01') | date('F') }}
{% endmacro %}

You can use it like this:

{% import _macros/utils as m_utils %}

{% for month in range(startMonth, endMonth, 1) %}
  {{ m_utils.monthNameFromNumber(month) }}
{% endfor %}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.