6

How can I use 'xx time ago' for date format in Drupal 8 nodes ?

I want to replace "xx time ago" with {{ date }} in node.

In Drupal 7 it worked with this code :

<?php
 print format_interval(time()-$node->created);
?>
9
  • Can you clarify what your objective is? Where do you want to display "time ago"? Which fields do you want to display "time ago"? Have you done any work on this?
    – mradcliffe
    Commented Apr 26, 2016 at 14:36
  • 1
    Can you expand on what you mean? Just just pick that display format under Manage Display, and then pick your options.
    – mpdonadio
    Commented Apr 26, 2016 at 14:39
  • I want replace "xx time ago" with {{ date }} in node
    – user60258
    Commented Apr 26, 2016 at 14:45
  • Please update the question with extra details.
    – nvahalik
    Commented Apr 26, 2016 at 14:58
  • So basically, drupal.stackexchange.com/questions/95376/…
    – mradcliffe
    Commented Apr 26, 2016 at 15:24

5 Answers 5

16

There are two ways to tackle this.

One is to just use the field formatters. If you have a DateTime field, just goto Manage Display, and change the Format to Time ago. Then click the gear, and pick some options. These are cache aware that will bubble up through the page, but you may end up with short cache lifetimes in some situations.

The other is to use a template_preprocess_node(). This is preferable when you have a timestamp that isn't a field. Then you use the date formatter service to render out the timestamp in timeago format. It is preferable to use the formatDiff() versions rather than formatInterval() (while not formally deprecated, it is discouraged).

function MYTHEME_preprocess_node(&$variables) {
  /** @var \Drupal\Core\Datetime\DateFormatterInterface $formatter */
  $date_formatter = \Drupal::service('date.formatter');
  $request_time = \Drupal::time()->getRequestTime();
  $variables['foo'] = $date_formatter->formatDiff($request_time - 12345, $request_time, [
    'granularity' => 3,
    'return_as_object' => TRUE,
  ])->toRenderable();
}

When you specify 'return_as_object' => TRUE with the formatDiff() functions, a FormattedDateDiff object gets returned, which contains the formatted string as well as a mostly accurate [#cache]['max-age'] entry in a render array to make this work with Drupal 8's new caching system. Then you can just use {{ foo }} in your Twig template; the render engine will do the right thing with the render array instead of a plain string.

Also read the docs on DateFormatterInterface for the formatTimeDiffSince() and formatTimeDiffUntil() variants, and for the $options you can pass in.

4

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Datetime%21DateFormatter.php/function/DateFormatter%3A%3AformatTimeDiffSince/8.2.x

$this->date->formatTimeDiffSince($time_stamp);

or

\Drupal::service('date.formatter')->formatTimeDiffSince($time_stamp);

2
  • works perfectly Commented Jul 23, 2019 at 6:12
  • Thanks for sharing. Very useful to know when working with timestamps in non-entity related context (for example formatting cron last run read from State API).
    – Balu Ertl
    Commented Apr 29 at 15:43
2

The easiest approach is to prepare it in ỳourtheme_preprocess_node() and then just print it in the twig template.

However, with D8's render caching, trying to do a time ago output on the server side can not work, unless you disable caching. It will be calculated on the first request and then never change again.

Instead, you want to send the time in an easy to parse markup, and then use JS to display it as a time ago format. See how d.o does that for comment dates: https://www.drupal.org/node/2704717 (it also includes functionality to switch between relative and absolute dates with a double click).

3
  • Well, drupal.org/node/2500525 landed, so timeago on anything using the formatters should work, which will set some reasonable TTLs on the elements. You can also just set the max-age to 0 in #cache, and let that prevent caching for you, or pick your own lifetime.
    – mpdonadio
    Commented Apr 26, 2016 at 19:48
  • 1
    Looks like there is a module for this now, drupal.org/project/twig_extensions, see Date: Adds a filter for rendering the difference between dates. and then the documentation at twig.sensiolabs.org/doc/extensions/date.html, thus {{ date|time_diff }} Commented Apr 26, 2016 at 21:56
  • @DannyEnglander Yeah, that is from one of the theme system maintainers. Personally, I would opt for using the Drupal methods to take into account cache contexts, timezone, translation, etc.
    – mpdonadio
    Commented Apr 26, 2016 at 22:56
2

Twig has a native Date extension that provides a "Time Ago" filter

See http://twig.sensiolabs.org/doc/extensions/date.html

|time_diff is the one you want. The problem is Drupal doesn't include this extension by default.

So to get this in your twig templates do the following

  • Install Twig Extensions Drupal Module (Be sure to follow the instructions) - https://www.drupal.org/project
  • In Terminal in your Drupal Site
    • $ composer require twig/extensions
    • (be patient ... it took a while)
  • Enable Module
  • Use the Filter in your Twig templates

    {{ field_my_date|time_diff }}

Renders like "10 MONTHS AGO"

3
  • There isn't much documentation, so some experimentation may be in order. For me, I got it working with {{ node.getCreatedTime|time_diff }} . It may take some rooting through your theme templates to find what fields are available.
    – karolus
    Commented Nov 28, 2018 at 6:37
  • this isnt a Drupal module (or it would come from drupal/{project} in composer; so what does "enable module" mean?
    – liquidcms
    Commented Jul 5, 2023 at 17:41
  • This has to be added as a service. See here: stackoverflow.com/questions/26311197/twig-time-ago-format
    – liquidcms
    Commented Jul 5, 2023 at 17:48
0

Here is Answer,

in your .theme file add below code

function themename_preprocess_comment(&$variables) {

  $date = $variables['comment']->getCreatedTime();
  $variables['created'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $date);
  $variables['submitted'] = t('@author', array('@author' => $variables['author'], '!datetime' => '<span class="comments-ago ">' . $variables['created'] . ' ago </span>'));

}

and render in your comment.html.twig file below code

{{ created }} {{ 'ago'|t }}

hope it will helpfull thank you...

Your Answer

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