Is there anyway to get my date formats looking like Facebook? I'd like to get my articles to have this as a date format: "5 min ago", "yesterday", "3 days ago", "4 months ago" and then once it reaches a full year ago, make it have a date format like "Dec 5, 2016".

If anyone has gotten this working, would you mind sharing with me(and the world) your code on how to achieve this in Twig?

Thanks in advance!

2 Answers 2


Chiming in with a solution made from reading the above solution and comments. I also wrapped it in a macro.

{% macro timeAgo(entry) %}

    {% set dateOneHourAgo = now.modify('- 1 hour') %}

    {% set elapsedMinutes = entry.myDateField.diff(now).m %}

    {% if not (entry.myDateField < dateOneHourAgo) %}

        {{ entry.myDateField.diff(now) | duration | split('and') | first }} ago

    {% else %}

        {{ entry.myDateField.diff(now) | duration | split(',') | first }} ago

    {% endif %}

{% endmacro %}
  • Better late than never. This will help me out in the near future! Thanks! Commented Nov 28, 2019 at 15:06

It looks as though Craft 3’s built-in duration Twig filter might help:

Posted {{ entry.myDateField.diff(now) | duration }} ago.

With a bit of additional logic, you can make this more useful, after an Entry leaves a specified window:

{% set dateOneYearAgo = now.modify('- 1 year') %}
{% set dateOneMonthAgo = now.modify('- 1 month') %}
{% set dateOneDayAgo = now.modify('- 1 day') %}

{% set elapsedMonths = entry.myDateField.diff(now).m %}
{% set elapsedDays = entry.myDateField.diff(now).d %}

{% if entry.myDateField < dateOneYearAgo %}
    {# Posted longer ago than one year... #}
    Posted on {{ entry.myDateField | date('M j, Y') %}
{% elseif entry.myDateField < dateOneMonthAgo %}
    {# Posted longer ago than one month (but more recently than one year, as we caught that, above)... #}
    Posted {{ elapsedMonths }} month{{ elapsedMonths != 1 ? 's' : '' }} ago
{% elseif entry.myDateField < dateOneDayAgo %}
    {# Posted longer ago than one day (but, as above, more recently than a month ago)... #}
    Posted {{ elapsedDays }} day{{ elapsedDays != 1 ? 's' : '' }} ago
{% else %}
    Posted {{ entry.myDateField.diff(now) | duration }} ago.
{% endif %}

The if statements compare the date objects, and returns true if entry.myDateField is earlier than the date one year ago (- 1 year), one month ago (-1 month), etc.

now.modify(…) is a convenient and human-readable way of getting a date relative to the current time—you can pass this method any relative date string.

The ternary statements (like {{ elapsedDays != 1 ? 's' : '' }}) are just a crummy way of properly pluralizing the units of time—I'd recommend using the Typogrify plugin, instead, as it offers some more declarative ways to handling this— say, {{ 'month' | pluralize(elapsedDays) }}.

Note: I've omitted special circumstances for things like “yesterday,” as these constraints can be layered in as new else if statements—just be sure to put the tightest constraints at the top, so that it matches your priorities (i.e. a test for “last week” should come after a test for “yesterday”). Anything you don't care about can fall through to the default duration filter.

  • 1
    DateTimeHelper::secondsToHumanTimeDuration and DateTimeHelper::humanDurationFromInterval() might be handy, too.
    – Brad Bell
    Commented Nov 7, 2018 at 21:39
  • Alright, so I gave it a try, and I'm not sure what you did with now.modify, can you explain? Also I tried both examples you have up there but always got back a very full date like this : Posted 21 days, 22 hours, and 49 minutes ago. Is there a way to simplify it and to keep only the first element which in this case would be "21 days"? Thanks Commented Nov 9, 2018 at 21:34
  • Didn't know this about the output of the duration filter! Based on the source, it looks like it'd be safe to just pick the first segment off of the returned value, split on the commas that join the units, i.e. {{ entry.myDateField.diff(now) | duration | split(',') | first }} Commented Nov 10, 2018 at 4:50
  • @AugustMiller Thanks a lot! I'm almost there. It is now spiting out 3 days but there seems to be an issue when its not a full day, it spits out 2 hours and 24 minutes. Is there a way to also remove the following: and 24 minutes ? Thank you! Commented Nov 13, 2018 at 22:31
  • I think you might be in the territory of just needing a couple more conditionals, rather than trying to parse + modify output—I'll update the answer to reflect another layer of scrutiny when deciding what output "style" to use. Commented Nov 14, 2018 at 18:29

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.