Another variation on the "time ago" PHP function, use MySQL's datetime field type

tags: PHP, sNews CMS, MySQL

I was recently looking at writing a function to format the comment post times in the ever trendy "time ago" style... such as;

Matt posted 6 days 3 hours ago

Naturally I first scoured the web for an appropriate existing PHP function, and I came across this one; http://wessite.com/item/2008/11/digg-like-time-ago-php-function (dead link).

Quite useful and fairly complete, but there were a few things I wanted to change, so I've hacked it up and remixed it here to accept a MySQL datetime field type result and then format the output like mentioned above. I also added weeks, months, years, and decades to the function to carry it as far out as anyone would possibly want it to go.

If you're using sNews and want to use this for your comments, simply follow these 2 quick steps.

Step 1) As always, BACK-UP your snews.php file and work off a copy. Now simply copy the function below into your snews.php file, right above the closing php tag;

// DISPLAYS COMMENT POST TIME AS "1 year, 1 week ago" or "5 minutes, 7 seconds ago", etc...
function time_ago($date,$granularity=2) {
    $date = strtotime($date);
    $difference = time() - $date;
    $periods = array('decade' => 315360000,
        'year' => 31536000,
        'month' => 2628000,
        'week' => 604800, 
        'day' => 86400,
        'hour' => 3600,
        'minute' => 60,
        'second' => 1);
    if ($difference < 5) { // less than 5 seconds ago, let's say "just now"
        $retval = "posted just now";
        return $retval;
    } else {                            
        foreach ($periods as $key => $value) {
            if ($difference >= $value) {
                $time = floor($difference/$value);
                $difference %= $value;
                $retval .= ($retval ? ' ' : '').$time.' ';
                $retval .= (($time > 1) ? $key.'s' : $key);
                $granularity--;
            }
            if ($granularity == '0') { break; }
        }
        return ' posted '.$retval.' ago';      
    }
}

Step 2) Now find the function comment, and comment out the existing date format and add the highlighted code like below;

while ($r = mysql_fetch_array($result)) {
    //$date = date($date_format, strtotime($r['time']));
    $date = time_ago($r['time']);
    $commentNum = $offset + $ordinal;

That should do it, now your comment times should be formatted by "time ago". I just thought it may be useful to someone else looking for the functionality.


Like this post?
Did you find this post useful? Do you have something to add? Why not leave a comment below and add to the conversation, or subscribe to my RSS feed and get posts like this delivered automatically to your feed reader.



Comments

RSS Comments Feed


slemborg's Avatar


Looking really good, i'm gonna try it out tomorrow, good job.

Pico RG's Avatar


Thanks for the script, it seems very interesting

Michael's Avatar


Thanks for the function, but it has an error in it. The 'round' should be 'floor' or 'intval'. As an example, if you pass it a date that is between 23.5 and 24 hours in the past, it will return '24 hours 30+x minutes ago', but it should return '23 hours 30+x minutes ago'.

Matt's Avatar


Good catch Michael, it should use floor. I will change that. Thanks!

Eric's Avatar


Thanks Matt, I was looking for just this thing, and it works like a champ. Saved me a bunch of time, I'm sure.

Sushi's Avatar


Hey. Great script! Just wondering if it's possible to make the posts the same time format? Mainly because I don't use the comments on my snews install. I had a little poke around but had no luck so far. Any help would be awesome :]

Matt's Avatar


Sushi,

Look within the function articles, find the following;

$a_date_format = date(s('date_format'), strtotime($r['date']));
and change it to;

$a_date_format = time_ago($r['date']);
I think that should do it.

Bodo's Avatar


Hello, I implemented the aboce function into my custom php script and it works fine for the yesterday posts. But the problem is that if I modified the date into the current date the script just shows 18+ hourse instead of minute.

Matt's Avatar


Bodo,

I'm not sure why that would happen, is the granularity is set to 2?

mochammad ichlas's Avatar


Thanks for the great information. I have a blog discussing web site design tips and usabilty. If you want to take a look.

dave's Avatar


I have no idea what i'm doing wrong (not very good at php) but on a test i did, it is saying "posted 4 decades one year ago" ??????

i'm pretty sure i can't time travel. =]

Matt's Avatar


Dave,

Are you sure you're giving the function a MySQL datetime result? 4 decades ago sounds like maybe you're getting the Unix timestamp due to an invalid date or something along those lines.

dave's Avatar


hmmm, I'm not really sure, I was trying to add this function to my forum. I'm using a mysql database with the unix time, but like i said i am really rubbish at php (just recently trying to teach myself).

Thanks for the reply and all but i think ill just leave it for now until i understand it all a bit better. Cheers.

jason's Avatar


fantastic function.. i installed. the only problem i am having is that i have my site reload the page as soon as some data is updated. but sometimes it reloads too fast and the function just reads 'posted ago'... but if i immediately refresh, then it corrects to something like 'posted 2 seconds ago'.. any tip on how to fix this?
thanks!

Matt's Avatar


Jason,

If it's because it's under 1 second, you could add a simple check in there, like;

if ($time < '1') {
$retval = "less than 1 second";
}
$granularity--;

That's totally untested BTW, may need some tweaking

Matt's Avatar


Thanks Aziz! I see now, I was checking the time instead of the difference, I should've looked a little closer. Thanks for posting a solution.

I have updated it to say "posted just now" when under 5 seconds, the user can change that to 1 second or any other value they like.

Joshua F's Avatar


This is better than sex.

Yogesh's Avatar


Thanks for this, its work perfect for me

Dan's Avatar


How do I implement this into the following function?:

$time = strtotime($message['pubdate']);

echo sprintf( __('%s', 'twitter-for-wordpress'),' '. date('m/d/Y H:ia', $time). '' );

Matt's Avatar


Dan, try changing that code to this;

$time = time_ago($message['pubdate']);
echo sprintf( __('%s', 'twitter-for-wordpress'),' '.$time);

Sorry for the slow reply, been crazy busy lately.

Salsan  India's Avatar


thanks for the time ago script. i was doing some r&d to make this.

Charles's Avatar


My php returned an error. The error said that $retval did not exist.

Before using $retval .= ..., shouldn't you declare $retval = ''; beforehand?

Thanks for the script!

Matt's Avatar


Hi Charles,

It probably is best practice to declare it first with a null value, but the variable will be created when first called, and it should be called within the if/else.

Maybe the MySQL datetime you're sending it isn't valid and therefore $retval is never created? In which case, declaring it would simple return a null value I would think. Not really sure how you used it within your own script, but if you've got it working now, it's all good I suppose.

Eric's Avatar


shouldn't commentNum = $offset + $ordinal; have '$' in front of it?



(optional, not publicly displayed) (optional)
Commenting Tips:
DO post comments that add to the conversation.
Don't use keywords for your name. Use "Anonymous" if you don't want to post your real name.
Don't post URLs unrelated to the topic.

Pingbacks

  1. Programmer's Goodies

Site News

About Matt

Privacy Policy | About Me
Copyright © 2002 - 2012 Matt Jones
Hand crafted with HTML5 & CSS3
↑ Back to top