How can I output a timeframe in fully written notation nicely? Let's say you have two dates and want to output the timeframe in fully written "day month year - day month year" notation, but want to leave out the month and year parts of the start date if unnecessary.

Examples:


2014-06-13 to 2014-06-20 yields 13 – 20 June 2014
2014-06-13 to 2014-07-13 yields 13 June – 13 July 2014
2014-06-13 to 2015-06-13 yields 13 June 2014 – 13 June 2015


How can I get the desired notation of the timeframe?
Add the following macro to your template or import it with a separate twig file. The script allows the start and end date to be the same and outputs a single date instead of a timeframe.

Example:

2014-06-13 to 2014-06-13 yields 13 June 2014

The macro:

{% macro timeframe(dateStart, dateEnd) %}

    {# Output day of the start date if necessary #}
    {{ dateStart != dateEnd ? dateStart|date('j') }}

    {# Output month of the start date if necessary #}
    {{ dateStart|date('FY') != dateEnd|date('FY') ? dateStart|date('F') }}

    {# Output year of the start date if necessary #}
    {{ dateStart|date('Y') != dateEnd|date('Y') ? dateStart|date('Y') }}

    {# Output a hyphen if necessary #}
    {{ dateStart != dateEnd ? ' - ' }}

    {# Output end date #}
    {{ dateEnd|date('j F Y') }}

{% endmacro %}


Example usage:

{# Import external `macros.html` #}
{% import "macros.html" as macros %}

{# Call the macro #}
{% macros.timeframe(entry.exhibitionDateStart, entry.exhibitionDateEnd) %}


.

Edit:

Updated the macro to additionally support "month day, year" notation. The returned notation depends on the localeId attribute passed to the macro (eg. "en_us"). But you probably want to use the current locale's id, craft.locale for that ;)

Examples:


2014-06-13 to 2014-06-13 yields June 13, 2014
2014-06-13 to 2014-06-20 yields June 13 – 20, 2014
2014-06-13 to 2014-07-13 yields June 13 – July 13, 2014
2014-06-13 to 2015-06-13 yields June 13, 2014 – June 13, 2015


The updated macro:

{% macro timeframe(dateStart, dateEnd, localeId) %}

    {# Define locales where 'j. F - j. F Y' format is desired #}
    {% set locales_jFY = ['de', 'it', none] %}

    {# Define locales where 'F j. - F j., Y' format is desired #}
    {% set locales_FjY  = ['en'] %}

    {# Return timeframe for `locales_jFY` locales #}
    {% if localeId in locales_jFY %}

        {# Output day of the start date if necessary #}
        {{- dateStart != dateEnd ? dateStart|date('j. ') -}}

        {# Output month of the start date if necessary #}
        {{- dateStart|date('FY') != dateEnd|date('FY') ? dateStart|date('F ') -}}

        {# Output year of the start date if necessary #}
        {{- dateStart|date('Y') != dateEnd|date('Y') ? dateStart|date('Y') -}}

        {# Output a hyphen if necessary #}
        {{- dateStart != dateEnd ? ' - ' -}}

        {# Output end date #}
        {{- dateEnd|date('j. F Y') -}}

    {# Return timeframe for `locales_FjY` locales #}
    {% elseif localeId in locales_FjY %}

        {# Check if dates are on the same day but in different years #}
        {% if (dateStart|date('Fj') == dateEnd|date('Fj')) and (dateStart|date('Y') != dateEnd|date('Y')) %}
            {% set sameDaydiffYear = true %}
        {% endif %}

        {# Output month and day of the start date #}
        {{- dateStart|date('F j') -}}

        {# Output year of the start date if necessary #}
        {{- dateStart|date('Y') != dateEnd|date('Y') ? dateStart|date(', Y') -}}

        {# Output a hyphen if necessary #}
        {{- dateStart != dateEnd ? ' - ' -}}

        {# Output month of the end date if necessary #}
        {{- dateStart|date('F') != dateEnd|date('F') or sameDaydiffYear ? dateEnd|date('F ') -}}

        {# Output day of the end date if necessary #}
        {{- dateStart|date('Fj') != dateEnd|date('Fj') or sameDaydiffYear ? dateEnd|date('j') -}}

        {# Output year of the end date #}
        {{- dateEnd|date(', Y') -}}

    {% endif %}

{% endmacro %}