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

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

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.

Tags

 

You might like

Comments


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


Thanks for the script, it seems very interesting


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'.


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


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


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 :]


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.


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.


Bodo,

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


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


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. =]


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.


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.


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!


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


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.


This is better than sex.


Thanks for this, its work perfect for me


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). '' );


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.


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


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!


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.


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



(optional, not publicly displayed) (optional)

Pingbacks

  1. Programmer's Goodies

Copyleft 2002 - 2014 Matt Jones
Hand crafted with HTML5 & CSS3
↑ Back to top