Relative Dates in WordPress Templates

Over the weekend while I was working on the blog re-design I decided that in the new design I’d use more relative dates rather than actual dates when displaying an entries publication date and a comment’s date.

Especially with comments, I’d much rather know that it was posted a month ago than ‘May 23, 2008 at 9:42am’.

I first decided on the time ranges:

  • a moment ago (less than 1 min)
  • 1 min – 59 mins
  • 1 hour – 23 hours
  • 1 day – 7 days
  • 1 week – 5 weeks
  • 1 month – 11 months
  • 1 year – infinity years

Working with Time

When working with dates and times in PHP, as well as any other server side language it’s easiest to perform mathematical calculations using the date/time’s Unix time stamp (the number of seconds since Unix Epoch – Jan 1, 1970.)

To convert to a relative time you’d take the current time stamp using the time() function and subtract the relative date’s time stamp. You’d then use the difference and see where, in the relative range, it lands.

{googlead}

Calculating Time using the Difference

Here’s the function, I created to calculate the relative time, and added it to our theme’s functions.php file. I created to calculate the relative time:

PHP

<?php
    if(!function_exists('how_long_ago')){
        function how_long_ago($timestamp){
            $difference = time() - $timestamp;

            if($difference >= 60*60*24*365){        // if more than a year ago
                $int = intval($difference / (60*60*24*365));
                $s = ($int > 1) ? 's' : '';
                $r = $int . ' year' . $s . ' ago';
            } elseif($difference >= 60*60*24*7*5){  // if more than five weeks ago
                $int = intval($difference / (60*60*24*30));
                $s = ($int > 1) ? 's' : '';
                $r = $int . ' month' . $s . ' ago';
            } elseif($difference >= 60*60*24*7){        // if more than a week ago
                $int = intval($difference / (60*60*24*7));
                $s = ($int > 1) ? 's' : '';
                $r = $int . ' week' . $s . ' ago';
            } elseif($difference >= 60*60*24){      // if more than a day ago
                $int = intval($difference / (60*60*24));
                $s = ($int > 1) ? 's' : '';
                $r = $int . ' day' . $s . ' ago';
            } elseif($difference >= 60*60){         // if more than an hour ago
                $int = intval($difference / (60*60));
                $s = ($int > 1) ? 's' : '';
                $r = $int . ' hour' . $s . ' ago';
            } elseif($difference >= 60){            // if more than a minute ago
                $int = intval($difference / (60));
                $s = ($int > 1) ? 's' : '';
                $r = $int . ' minute' . $s . ' ago';
            } else {                                // if less than a minute ago
                $r = 'moments ago';
            }

            return $r;
        }
    }
?>

For me that was the easy part. It’s just math, and math is not only fun but very easy for me to work with. WordPress’s tags though, can sometimes be a little bit trickier.

WordPress, Working with Times

I started off with the comments and couldn’t find anything in WordPress Codex about comment date/time functions that would return a value for time instead of printing it to the screen, which would be critical for passing the number through the how_long_ago() function we just created.

So I went poking around in the WordPress core files and scripts and fount the get_comment_time() function, which is built into WordPress and returns a value using the PHP date string passed. So in place of the date rendering in my new template for the comments I used:

PHP

<?php if(!function_exists('how_long_ago')){comment_date() . ' at ' . comment_time(); } else { echo how_long_ago(get_comment_time('U')); } ?>

This will print the relative measurement if we do have the how_long_ago() function in out functions.php file, and it will print the susal date if for sme reason we have forgotten to add the function to our files.

For entries you can use get_the_time() function, like so:

PHP

<?php if(!function_exists('how_long_ago')){the_time('F jS, Y'); } else { echo how_long_ago(get_the_time('U')); } ?>

Pretty easy, and a great way to change up your theme, and possibly make it more relevant since people understand and usually think in relative terms.

This site runs on the Thesis WordPress Theme

Thesis Theme thumbnail

If you're someone who doesn't understand a lot of PHP, HTML, or CSS, Thesis will give you a ton of functionality without having to alter any code. For the advanced, Thesis has incredible customization possibilities via extensive hooks and filters. And with so many design options, you can use the template over and over and never have it look like the same site.

If you're more familiar with how websites work, you can use the fantastic Thesis User's Guide and world-class support forums to make more professional customizations than you ever thought possible. The theme is not only highly customizable, but it allows me to build sites with a much more targeted focus on monetization than ever before. You can find out more about Thesis below:

{ 29 comments }

1 Stefan October 2, 2008 at 1:27 am

I was trying this on my redesign and for some reason all the $difference’s ware negative until I changed them to:
$difference = $timestamp – time();
And now it’s working correctly. Seems strange to me too, but it does…

2 Stefan October 2, 2008 at 3:06 am

Forget my last comment, it wasn’t that :)
Took me long enough to figure out but it was negative because in “$difference = time() - $timestamp;” the time() gets the server timestamp and the $timestamp (which is get_comment_time('U')), is the WordPress time which includes the offset set in the options page.
From what they say on http://codex.wordpress.org/Function_Reference/current_time , using current_time('timestamp') instead of time() should work but it didn’t… I still had to add my time zone offset in the code.

3 Andrew October 3, 2008 at 7:38 am

Nice coding – yes it’s good to personalise the timestamps according to the visitor (i.e. when they are reading the comments). I see digg.com does this now too.

4 Josh December 20, 2008 at 11:42 am

This function is great. Thanks!

5 Stephanie Leary February 3, 2009 at 3:04 pm

There is a built-in WordPress function that does something similar, but it’s less elegant:

echo humantimediff(getthetime('U'), time()) . " ago";

It doesn’t calculate weeks, apparently, so you get things like “14 days ago.” I like yours much better!

6 Terri Ann
Twitter:
February 3, 2009 at 11:12 pm

Thanks Stephanie, for simple tasks like this I’d often rather use a function in the functions.php file since this is a great function to use in any other PHP code as well. I am a fan of portable code.

7 Melvyn April 22, 2009 at 12:18 pm

It didn’t work for me, the time just got stuck at “moments ago” and it’s been at least 40 mins ago since I last posted it. Anyone has this issue too? How do I get around it? Thanks!

8 Levani August 6, 2009 at 6:30 am

Great script, thanks!

How should I modifiy it to count seconds as well? I would like to display secons if the post isn’t at least one minutes old instead of “moments ago”.

9 Samiha October 7, 2009 at 6:20 pm

Terri, thanks for the great codes. I appreciated it!

10 Giuseppe November 29, 2009 at 10:51 pm

I Terri, I really like your function! I’m not an expert in PHP, if I want write “hour” and “hours” in italian (“ora” and “ore”), how i can do it? Thanks

11 Idiot Diet January 12, 2010 at 1:28 pm

Wahey thanks for that!

I like it a lot! I could never see the point on some of my blogs why I would need the exact date and time!

Thanks again

Yvonne

12 WSz February 5, 2010 at 5:52 am

Thanks for the code. Elegant and totally interoperable solution. I avoid installing plug-ins like the plague! Rather just do a call and off I go ;)

Great contributions dude!

13 Mike March 11, 2010 at 10:06 am

Great solution. I love when I can improve the installation with some simple function rather than a plugin.

Regarding this function, you’ll need to make sure you get the offset right in relation to your server. You’ll figure out pretty quickly what that offset should be by noting the difference between when your comments say they were posted and what this function spits out. To set the offset just change this line:

$difference = time() - $timestamp;

to something like the following if you have a four hour difference between your server time and the time that you have set for your installation:

$difference = (time() - 14400) - $timestamp;

To get that number just take hours6060 to get the seconds you’ll need for the offset. If you’re ahead, just add the seconds; behind, subtract them.

14 Mike March 11, 2010 at 10:07 am

That should be hours x 60 x 60 above. The multiplication symbol was removed.

15 Chevas March 16, 2010 at 1:33 pm

Thanks for writing this. Now, I just need to figure out how to cut it off after weeks just to use the date. :)

16 Terri Ann
Twitter:
March 16, 2010 at 2:09 pm

@Chevas I’ve removed the first if decision and replaced the second one with a date return. I think this would solve your dilemma. Just change the date function to return the format you want.

< ?php
    if(!function_exists('how_long_ago')){
        function how_long_ago($timestamp){
            $difference = time() - $timestamp;

            /*if($difference >= 60*60*24*365){        // if more than a year ago
            $int = intval($difference / (60*60*24*365));
            $s = ($int > 1) ? 's' : '';
            $r = $int . ' year' . $s . ' ago';
        } else*/
        if($difference >= 60*60*24*7*5){  // if more than five weeks ago
            $r = date('y-m-d', $timestamp);
        } elseif($difference >= 60*60*24*7){        // if more than a week ago
            $int = intval($difference / (60*60*24*7));
            $s = ($int > 1) ? 's' : '';
            $r = $int . ' week' . $s . ' ago';

            /* [..Put the rest of the code in..] */

17 johan August 24, 2010 at 6:44 am

Nice script. But how can I get the time to be for the last modified time instead of when the post was created. Thanks!

18 Technodo October 5, 2010 at 5:16 am

This is the best solution I have come across. Better than using a plugin or the WordPress humantimediff function.

19 guido November 24, 2010 at 9:53 am

how do I get the plural form?! I translated the function in Italian but it doesn’t work and I see only singular item…. plese help! already tried to hard coding the function but without results….
thanks in advance!

20 guido November 24, 2010 at 10:11 am

did you find a solution for your problem? i’ve got the same problem and trying to figure out how to make plural in italian but no way…. i’m desperate!!

21 Terri Ann
Twitter:
November 24, 2010 at 12:21 pm

@guido – Internationalization isn’t usually my strong suit but I restructured the code to allow for easier translations. The problem is in English we toss and ‘s’ at the end of most words to pluralize it. According to Google Translate in Itallian the plural form is a completely different word.

function howlongago() in Italian: (roughly translated via Google Translate)

    if(!function_exists('how_long_ago')){
        function how_long_ago($timestamp){
            $difference = time() - $timestamp;
        if($difference >= 60*60*24*365){        // if more than a year ago
            $int = intval($difference / (60*60*24*365));
            $s = (bool)($int > 1);
            $r = $int . ' ' . (($s)?'anni':'anno') . ' fa';
        } elseif($difference >= 60*60*24*7*5){  // if more than five weeks ago
            $int = intval($difference / (60*60*24*30));
            $s = (bool)($int > 1);
            $r = $int . ' ' . (($s)?'mesi':'mese') . ' fa';
        } elseif($difference >= 60*60*24*7){        // if more than a week ago
            $int = intval($difference / (60*60*24*7));
            $s = (bool)($int > 1);
            $r = $int . ' ' . (($s)?'settimane':'settimana') . ' fa';
        } elseif($difference >= 60*60*24){      // if more than a day ago
            $int = intval($difference / (60*60*24));
            $s = (bool)($int > 1);
            $r = $int . ' ' . (($s)?'giorni':'giorno') . ' fa';
        } elseif($difference >= 60*60){         // if more than an hour ago
            $int = intval($difference / (60*60));
            $s = (bool)($int > 1);
            $r = $int . ' ' . (($s)?'ore':'ora') . ' fa';
        } elseif($difference >= 60){            // if more than a minute ago
            $int = intval($difference / (60));
            $s = (bool)($int > 1);
            $r = $int . ' ' . (($s)?'minuti':'minuto') . ' fa';
        } else {                                // if less than a minute ago
            $r = 'pochi minuti fa';
        }
        return $r;
    }
}
22 Terri Ann
Twitter:
November 24, 2010 at 12:27 pm

A better solution than always accounting for the server time difference is to make the server time reflect the time you want it to with php function datedefaulttimezone_set()

23 Nijen January 2, 2011 at 7:28 am

Great code! I too love to write functions that I want directly into the theme. Much prefer that before plugins.
Thanks a lot for sharing Terri!

24 Jamie February 14, 2011 at 12:34 pm

How do I use it on “custom_functions.php” of Thesis theme? Any idea? Thanks for any help!

25 Tony March 22, 2011 at 2:34 am

The calculated time difference should be:

$difference = currenttime('timestamp') - getthe_time('U');

26 moimikey June 30, 2011 at 12:28 pm

wordpress has had humantimediff() since version 1.5… you can just do this within the loop:

humantimediff( getthetime( ‘U’ ) )

27 Terri Ann
Twitter:
July 22, 2011 at 9:50 am

Yup Moimikey is correct, that humandifftime() method is available in WordPress, here’s the documentation link to it: http://codex.wordpress.org/FunctionReference/humantime_diff

I still think this is a relevant post though, there are times you don’t want to expose a post or comment was written x years ago or x months ago and would rather say something like “a while back” or clever and quippy like “long ago and far away” and the function I’ve provided allows for customizations like that. But if you are looking for a quick and precise relative time the built in function will suit you without any additional code!

Thanks for the reminder Moimikey!

28 SK October 19, 2011 at 1:23 pm

Hi there,

I would like to make relative date visible up to 7 days and than showing normal date not relative time. is it possible to do it? and let me know please thanks

SK

29 Alex Pascal February 17, 2012 at 4:53 pm

This is the correct solution. Thanks so much!

Comments on this entry are closed.

{ 2 trackbacks }

Previous post:

Next post: