A Better Way to Add “Time Ago” to Your WordPress Theme

You may have noticed the cool little featured here on my personal blog where, instead of showing the date of the current WordPress post in the typical format, I’m showing it in the Twitter-like “time ago” format. In this tutorial I’ll show you exactly how I’m doing it and how you can incorporate the same thing into your WordPress theme.

Background Information

When I was designing this blog, I was really trying to get into the spirit of this whole micro-blogging meets-regular blog-meets Tumblr feel and also utilize WordPress post formats (introduced in WordPress 3.1). So, I thought it would totally fit the style of it all to somehow incorporate the Twitter-like format of showing when each post was published. For me personally, I can never keep track of what month or even what year it is sometimes. I guess the more time I spend on the Internet, the more fried my brain becomes. So, for me, it’s much quicker to comprehend if I can see that a post was published “3 years ago,” opposed to seeing a date and trying to do quick math in my head.

I assumed this would be something many people are doing and that I’d be able to quickly find a code snippet that I could copy and paste into my WordPress theme, but I was definitely wrong on that one. I came across several sites all referencing how to accomplish this in a similar way, but all weren’t really ideal for me.

Most of the examples I found all utilized the built-in WordPress function, human_time_diff. It was super easy to just take the publish date of a post, run it through this function, and display something similar to what I wanted. The problem though was that this WordPress function will only return this “human time difference” in the number of days. So for example after a month, you’d end up with something like “32 days ago,” and after a year, “165 days ago.”

I’m not really sure why WordPress would have the human_time_diff function in there with such a mediocre result. I think the function is more intended to be used for a short period of time. Either way, it’s even been brought up over on WordPress trac, but I guess they didn’t care too much about improving it.

However, one of the people that commented on that particular WordPress trac ticket actually linked to a function found in BuddyPress that does exactly what I was wanting to do.

So, it was BuddyPress’s bp_core_time_since function that inevitably lead me to my answer. I took their function and adapted it into something that could be used with the standard WordPress loop by hooking into WordPress’s the_time function.

The idea of adding it as a filter to WordPress’s the_time function I got from Lam Nguyen on his post:

Quick Tip: Display Timeago For WordPress If Less Than 24 Hours

I guess the chunk of the title of that post, “if less than 24 hours” pretty much sums up why using the human_time_diff WordPress function won’t work for what I was wanting to do.

The Code

The code I’m about to show is a little long, but it will allow you to display when your posts were published in a nice, user-friendly format that increments how the image below shows:

Step 1

First, copy this code into your functions.php file (or wherever in your theme you want – advanced theme authors generally will organize their functions in more files that just the functions.php).

function themeblvd_time_ago() {
	
	global $post;
	
	$date = get_post_time('G', true, $post);
	
	/**
	 * Where you see 'themeblvd' below, you'd
	 * want to replace those with whatever term
	 * you're using in your theme to provide
	 * support for localization.
	 */ 
	
	// Array of time period chunks
	$chunks = array(
		array( 60 * 60 * 24 * 365 , __( 'year', 'themeblvd' ), __( 'years', 'themeblvd' ) ),
		array( 60 * 60 * 24 * 30 , __( 'month', 'themeblvd' ), __( 'months', 'themeblvd' ) ),
		array( 60 * 60 * 24 * 7, __( 'week', 'themeblvd' ), __( 'weeks', 'themeblvd' ) ),
		array( 60 * 60 * 24 , __( 'day', 'themeblvd' ), __( 'days', 'themeblvd' ) ),
		array( 60 * 60 , __( 'hour', 'themeblvd' ), __( 'hours', 'themeblvd' ) ),
		array( 60 , __( 'minute', 'themeblvd' ), __( 'minutes', 'themeblvd' ) ),
		array( 1, __( 'second', 'themeblvd' ), __( 'seconds', 'themeblvd' ) )
	);

	if ( !is_numeric( $date ) ) {
		$time_chunks = explode( ':', str_replace( ' ', ':', $date ) );
		$date_chunks = explode( '-', str_replace( ' ', '-', $date ) );
		$date = gmmktime( (int)$time_chunks[1], (int)$time_chunks[2], (int)$time_chunks[3], (int)$date_chunks[1], (int)$date_chunks[2], (int)$date_chunks[0] );
	}
	
	$current_time = current_time( 'mysql', $gmt = 0 );
	$newer_date = strtotime( $current_time );

	// Difference in seconds
	$since = $newer_date - $date;

	// Something went wrong with date calculation and we ended up with a negative date.
	if ( 0 > $since )
		return __( 'sometime', 'themeblvd' );

	/**
	 * We only want to output one chunks of time here, eg:
	 * x years
	 * xx months
	 * so there's only one bit of calculation below:
	 */

	//Step one: the first chunk
	for ( $i = 0, $j = count($chunks); $i < $j; $i++) {
		$seconds = $chunks[$i][0];

		// Finding the biggest chunk (if the chunk fits, break)
		if ( ( $count = floor($since / $seconds) ) != 0 )
			break;
	}

	// Set output var
	$output = ( 1 == $count ) ? '1 '. $chunks[$i][1] : $count . ' ' . $chunks[$i][2];
	

	if ( !(int)trim($output) ){
		$output = '0 ' . __( 'seconds', 'themeblvd' );
	}
	
	$output .= __(' ago', 'themeblvd');
	
	return $output;
}

// Filter our themeblvd_time_ago() function into WP's the_time() function
add_filter('the_time', 'themeblvd_time_ago');

View this code on Pastie: http://pastie.org/1785073

Make sure to take note of that last add_filter part on the very last line. That's an important part because that's where our long function actually gets tied into WordPress. Without it, we just have a random function sitting there, not doing anything!

Step 2

So, now that you've copied the above code into your theme, it's super easy to utilize; simply use the_time() in your theme file, and it will display in our new and improved "time ago" format.

Here's a really simple example of standard WordPress loop:



	

by

Sorry, no posts matched your criteria.

Where you see "the_time" function being used in the snippet above, it will display as we want. It's possible in your theme you're already using the_time function, and so you may not even have to change anything. It will just be working from only doing step 1.

One thing to note though is that it's very common when using the_time function within your WordPress loop, that you will have designated a format to be used within the_time function like this:


Or something more like this, which is how you should have be doing it before (especially if this is commercial theme you're creating):


However, for this function to work properly now the way we've modified it, it would be best to call the_time function within our loop with no format simply like this:


38 comments on “A Better Way to Add “Time Ago” to Your WordPress Theme

    • I think a neat feature would be to change the Twitter-like time_ago into the normal year, month, day format when you hover over it.

      Completely unobtrusive, but helpful, I think. Thanks again!

  1. How would I use this very handy filter function only for a specific post type? Right now it filtlers all instances of the_time(). I want it to filter the_time for only one of my post types (classifieds).

    Thanks!

  2. I just wanted to let you know that I’ve used your code in almost all of my blogs! Excellent information, well explained! I even included it in a Greek blog, where I translated the time periods “month, year, day” but that resulted into question marks to appear in my blog’s pages. I found out quickly it was a matter of ANSI and UTF-8 coding! Worked perfectly!

    Many thanks!

  3. Just what I was looking for! Thanks.

    Like you, other tutorials I came across used human_time_diff() but, as I don’t post every day, your solution makes it look much more readable.

    Don’t know about you bit it’s hard working out actually how long ago ‘155 days’ is 🙂

    Thanks again

  4. I really want to add this to my site. but on some posts the time says “Sometime” I read the notes in the code saying there was a calculation error, but how can this be fixed?

  5. I’m having an issue with this…when a new post is published it says “Sometime” and after hours since it was posted it now says “2 Hours ago” This isn’t correct at all…
    what is going on here?

    • Try replacing $newer_date = strtotime( $current_time ); with $newer_date = time();

      I was converting the plugin for use with both comments and posts and this seems to have fixed it.

  6. Please help me. This script alway shows the GTM time but i want it to shows my local time, i change

    $date = get_post_time(‘G’,’true’,$post); to $date = get_post_time(‘U’,$post);

    But it still didnt work. Please help me

    • Hey there!
      You just need to change the time in the script – look in line 30:

      $current_time = current_time( ‘mysql’, $gmt = 0 );
      $newer_date = strtotime( $current_time );

      Just change the value after gmt, to whatever GMT time you’re living in.

  7. (geez it’s not easy to post something related to code on your site!! html tags are interpreted, and php tags are removed!)

    It’s really a bad idea to filter the_time as it prevents any other uses, for example in the twentytwelve theme the date is added in the GTM format to the “datetime” attribute of the ‹time› HTML5 tag:

    ‹time datetime="‹?php comment_time('c'); ?›"›‹?php comment_date(); ?›‹/time›

    Which outputs something like:

    ‹time datetime="2013-03-19T05:17:20+00:00"›March 19, 2013 at 5:17 am‹/time›

    Your filter breaks this functionality.

    Also, it is quit useless for the end-user to return “sometime” when an error occurs in the calculation, instead you should display the date of the comment, this way the end-user can at least make the calculation himself in his head.

    It’s better to not filter the_time and to provide an independent separate function.

    Finally, your function is not really translatable, let me explain: you force the word “ago” to be the last in the sentence, however this word order is correct almost only in English, but in many other languages the order of the words differs! For example, in French you would not say “5 minutes ago”, but something like “it has been 5 minutes” (i.e. “Il ya 5 minutes”, see http://translate.google.com/#en/fr/5%20minutes%20ago). As you can see I cannot translate your function into French as I cannot put any preceding words, and even if I could, I would have to translate ” ago” with “” (an empty string) which doesn’t make sense.

    To solve this situation you should make use of the printf() PHP function and provide replaceable values (variables) to the translator. Here is what I came up with:

    ‹?php
    	if (1 == $count) { // Singular
    		$output = sprintf(__('%1$s %2$s ago', 'myTheme'), $count, $chunks[$i][1]);
    	} else { // Plural
    		$output = sprintf(__('%1$s %2$s ago', 'myTheme'), $count, $chunks[$i][2]);
    	}
    ?›
    

    This is quit simple really, the output is exactly the same as yours and the translator now has the ability to play freely and constitute any sentence using the two available variables which are $count and the already translated words for “minutes/hours/days/etc.” in whatever order.

    I must say that I have the feeling that this function is too basic and incomplete to deal with time and human interpretation of it. What I mean is that I miss the natural “today”, “yesterday”, “last week/month/year”, just to name a few… because if we were to go there then we could even consider adding a few more case scenarios like “just now”, “a few moments ago”, “earlier today”, “this morning”, “last night”, “a couple of days ago”, “about a year ago” (when not exactly a year) or “last year”, and other appropriate sentences that are relevant to other languages (that might need cooperation from translators thoughts!).

    • function time_ago( $type = ‘post’ ) {
      $d = ‘comment’ == $type ? ‘get_comment_time’ : ‘get_post_time’;

      return human_time_diff($d(‘U’), current_time(‘timestamp’)) . ” ” . __(‘ago’);

      }

  8. How to manage this for sites not in English?

    In French you would say “il-y-a 3 mois” (3 months ago) but the function would provide you with “3 mois il-y-a”, if I’m not mistaken?

  9. Is there a way to switch time ago with places?
    Like ‘ago 20 minutes’ and not like now ’20 minutes ago’.
    Because in my country we spell it backwards.
    Thanks.

  10. Hi, Is it possible to only display “weeks ago” in this feature if post is published before 7 days and more. I don’t want to display month ago or years ago if post is that old. I just want to display weeks ago. If it can be done then please do help.

  11. Your code worked flawlessly on my website, just by putting it in functions.php. Before that I tried the wp-days-ago plugin but couldn’t incorporate it in the theme.

    Thanks.

Leave a Reply to Micahel Cancel reply

Your email address will not be published. Required fields are marked *


*