Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.x Fix a bug when |time_ago didn’t consider timezones correctly #2758

Merged
merged 2 commits into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/v2/guides/date-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ DateTimeHelper::time_ago($post->date());
**Twig**

```twig
{{ post.date|time_ago }}
{{ post.date('U')|time_ago }}
```

**HTML**
Expand Down
23 changes: 17 additions & 6 deletions src/DateTimeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,18 @@ public static function wp_date($format = null, $date = null, $timezone = null)
*
* Differentiates between past and future dates.
*
* @api
* @see \human_time_diff()
* @example
* ```twig
* {{ post.date('U')|time_ago }}
* {{ post.date('Y-m-d H:i:s')|time_ago }}
* {{ post.date(constant('DATE_ATOM'))|time_ago }}
* ```
*
* @param int|string $from Base date as a timestamp or a date string.
* @param int|string $to Optional. Date to calculate difference to as a timestamp or
* a date string. Default to current time.
* a date string. Default current time.
* @param string $format_past Optional. String to use for past dates. To be used with
* `sprintf()`. Default `%s ago`.
* @param string $format_future Optional. String to use for future dates. To be used with
Expand All @@ -78,14 +85,18 @@ public static function time_ago($from, $to = null, $format_past = null, $format_
$format_future = __('%s from now');
}

$to = $to === null ? time() : $to;
$to = is_int($to) ? $to : strtotime($to);
$from = is_int($from) ? $from : strtotime($from);
$to = $to ?? time();
$to = is_numeric($to)
? new \DateTimeImmutable('@' . $to, wp_timezone())
: new \DateTimeImmutable($to, wp_timezone());
$from = is_numeric($from)
? new \DateTimeImmutable('@' . $from, wp_timezone())
: new \DateTimeImmutable($from, wp_timezone());

if ($from < $to) {
return sprintf($format_past, human_time_diff($from, $to));
return sprintf($format_past, human_time_diff($from->getTimestamp(), $to->getTimestamp()));
} else {
return sprintf($format_future, human_time_diff($to, $from));
return sprintf($format_future, human_time_diff($to->getTimestamp(), $from->getTimestamp()));
}
}
}
9 changes: 9 additions & 0 deletions src/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -1307,19 +1307,28 @@ public function modified_timestamp()
* [`get_the_date`](https://developer.wordpress.org/reference/hooks/get_the_date/) filter to the
* output.
*
* If you use {{ post.date }} with the |time_ago filter, then make sure that you use a time
* format including the full time and not just the date.
*
* @api
* @example
* ```twig
* {# Uses date format set in Settings → General #}
* Published on {{ post.date }}
* OR
* Published on {{ post.date('F jS') }}
* which was
* {{ post.date('U')|time_ago }}
* {{ post.date('Y-m-d H:i:s')|time_ago }}
* {{ post.date(constant('DATE_ATOM'))|time_ago }}
* ```
*
* ```html
* Published on January 12, 2015
* OR
* Published on Jan 12th
* which was
* 8 years ago
* ```
*
* @param string|null $date_format Optional. PHP date format. Will use the `date_format` option
Expand Down
49 changes: 48 additions & 1 deletion tests/test-timber-dates.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php

use Timber\DateTimeHelper;
use Timber\Post;
use Timber\Timber;

/**
Expand Down Expand Up @@ -78,6 +77,54 @@ public function testTimeAgoWithPostDateTwigFilter()
$this->assertEquals($current_ago, $str);
}

/**
* @ticket https://github.com/timber/timber/issues/2737
* @return void
*/
public function testTimeAgoWithPostDateTwigFilterTimezoneAustralia()
{
$timezone_backup = get_option('timezone_string');

// Set timezone to Australia/Adelaide.
update_option('timezone_string', 'Australia/Adelaide');

$current_time = current_datetime();
// Subtract 3 hours to get a time in the past.
$post_date = $current_time->sub(new \DateInterval('PT3H'));

$post_id = $this->factory->post->create([
'post_date' => $post_date->format('Y-m-d H:i:s'),
]);
$post = Timber::get_post($post_id);

$diff1 = Timber::compile_string(
"{{ post.date('U')|time_ago }}",
[
'post' => $post,
]
);

$diff2 = Timber::compile_string(
"{{ post.date(constant('DATE_ATOM'))|time_ago }}",
[
'post' => $post,
]
);

$diff3 = Timber::compile_string(
"{{ post.date('Y-m-d H:i:s')|time_ago }}",
[
'post' => $post,
]
);

$this->assertEquals('3 hours ago', $diff1);
$this->assertEquals('3 hours ago', $diff2);
$this->assertEquals('3 hours ago', $diff3);

update_option('timezone_string', $timezone_backup);
}

public function testTimeAgoLabels()
{
$past = DateTimeHelper::time_ago('2016-11-29 02:00:00', '2016-11-30, 02:00:00', 'prePast %s afterPast');
Expand Down