Relative Date / Time Strings in PHP

published:
2009.01.20
topics:
php

I've noticed that Facebook, Twitter, and lots of other sites are using a relative date and time string description for user posts and comments. For example, "comment written about 3 months ago" instead of "comment written on October 20, 2008." I decided to do the same thing on this site, although rather than saying "3 months ago" I made it say "T plus 3 months." I adopted the NASA language for keeping track of post-launch time. If you've ever heard a NASA employee (or an actor portraying a NASA employee) say, "T minus 1 minute to lift off," that is their standard language for pre-launch time. Same idea. (Perhaps I'm taking this space thing a little too far... whatever. All in good fun.)

I want to share the PHP function I wrote to convert the timestamp of a comment or Tweet — or anything else — into a relative time string:

function time_elapsed_string($ptime) {
    $etime = time() - $ptime;
    
    if ($etime < 1) {
        return '0 seconds';
    }
    
    $a = array( 12 * 30 * 24 * 60 * 60  =>  'year',
                30 * 24 * 60 * 60       =>  'month',
                24 * 60 * 60            =>  'day',
                60 * 60                 =>  'hour',
                60                      =>  'minute',
                1                       =>  'second'
                );
    
    foreach ($a as $secs => $str) {
        $d = $etime / $secs;
        if ($d >= 1) {
            $r = round($d);
            return $r . ' ' . $str . ($r > 1 ? 's' : '');
        }
    }
}

I called the function time_elapsed_string() because really the timestamp you are converting is always relative to right now. The only argument $ptime must be a UNIX timestamp representing the date and/or time you want to convert to a relative time string. If you provide a timestamp that happens to be for right now, or you provide one that is actually in the future, then my code returns '0 seconds' immediately. This could easily be changed to 'less than 1 second' if you wish.

It is also important to note that I designed the string output of my function to only be as detailed as the largest block of time that has passed, whether than be a year, month, day, hour, minute, or second. That is to say, if you pass in a timestamp from 14 months ago, my function returns '1 year' not '1 year and 2 months'. Also, timestamps older than one year will simply return the relative number of years that have passed, e.g. '3 years'. Some other websites choose to return an actual datetime string like 'January 1, 2006' for timestamp older than a year. A change like this would be trivial to make if you wanted that behavior.

Of course, besides collapsing what would have been a long string of if-else-if blocks into an array and loop, part of the reason why this code is so succinct is that it doesn't support dates before the epoch (1970). That is fine for me, unless my commenters somehow figure out how to time travel — which I guess is a real possibility if they also take this space thing a little too far.