Reputation: 3799
I'm new to Twig and I'm looking to turn a datetime
format into a time ago like 2 hours ago or 3 days ago. There is a jquery plugin (jquery-timeago) that I've been using on the client side but it would be great if I can do this with twig. If twig doesn't come with this filter format are there extensions that I can use?
Upvotes: 11
Views: 23055
Reputation: 1010
An updated version of Mark S answer with translation as requested by @wawa
class TimeAgoTwigExtension extends AbstractExtension
{
public function __construct(private readonly TranslatorInterface $translator)
{
}
public function getFilters()
{
return [new TwigFilter('time_ago', [$this, 'timeAgo'])];
}
public function getFunctions()
{
return [new TwigFunction('time_ago', [$this, 'timeAgo'])];
}
public function timeAgo(\DateTimeImmutable $datetime): string
{
$time = time() - $datetime->getTimestamp();
$units = [
31536000 => 'shared.time_ago.year',
2592000 => 'shared.time_ago.month',
604800 => 'shared.time_ago.week',
86400 => 'shared.time_ago.day',
3600 => 'shared.time_ago.hour',
60 => 'shared.time_ago.minute',
1 => 'shared.time_ago.second',
];
foreach ($units as $unit => $text) {
if ($time >= $unit) {
$numberOfUnits = floor($time / $unit);
return $this->translator->trans($text, ['%count%' => $numberOfUnits], 'app');
}
}
return 'shared.time_ago.unknown';
}
}
This can then be translated as follows:
{1}a week ago|]1,Inf[ %count% weeks ago
Upvotes: 0
Reputation: 1630
Twig's date extension does exactly what you ask:
{{ post.published_at|time_diff }}
The example above will output a string like 4 seconds ago or in 1 month, depending on the filtered date.
See http://twig.sensiolabs.org/doc/extensions/date.html (no longer works) Working link http://twig-extensions.readthedocs.io/en/latest/date.html
To make this work, follow these steps:
composer require twig/extensions
When working with symfony add this to your services.yml
services:
twig.extension.date:
class: Twig_Extensions_Extension_Date
tags:
- { name: twig.extension }
Upvotes: 22
Reputation: 4010
If you're using Twig inside of Symfony, check out KnpTimeBundle. Includes "ago" support in multiple languages.
Upvotes: 7
Reputation: 3799
I found out I can create a custom filter with twig Twig_SimpleFilter
.
$filter = new Twig_SimpleFilter('timeago', function ($datetime) {
$time = time() - strtotime($datetime);
$units = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($units as $unit => $val) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
return ($val == 'second')? 'a few seconds ago' :
(($numberOfUnits>1) ? $numberOfUnits : 'a')
.' '.$val.(($numberOfUnits>1) ? 's' : '').' ago';
}
});
Then I add it to my Twig environment:
$twig = $app->view()->getEnvironment();//because I'm using Twig in Slim framework
$twig->addFilter($filter);
Use it my template like this:
{{2014-10-11 12:54:37|timeago}}
Upvotes: 15