Printing relative dates in php

A couple of days back while writing some date code for a messaging service, I required to print the date of the messages in a relative format – ‘today, ‘yesterday’, 3 weeks ago’ etc. I wrote a small function for the same. A sample run of the function is shown below.

echo DateToWords(time()) . "<br>";
echo DateToWords(time() - (3600 * 24 * 1)) . "<br>";
echo DateToWords(time() - (3600 * 24 * 4)) . "<br>";
echo DateToWords(time() - (3600 * 24 * 7)) . "<br>";
echo DateToWords(time() - (3600 * 24 * 14)) . "<br>";
echo DateToWords(time() - (3600 * 24 * 100)) . "<br>";
echo DateToWords(time() - (3600 * 24 * 366));

And the output for the above. For dates above 1 year it returns the actual date.

4 days ago
1 week ago
2 weeks ago
14 weeks ago

The function code is shown below.

/* Change the following constants to suit your language */
define('STRING_TODAY', "today");
define('STRING_YESTERDAY', "yesterday");
define('STRING_DAYS', "%d days ago");
define('STRING_WEEK', "1 week ago");
define('STRING_WEEKS', "%d weeks ago");
/* Change the following date format to your taste */
define('DATE_FORMAT', "m-d-Y");
/* The functions takes the date as a timestamp */        
function DateToWords($time)
    $_word = "";
    /* Get the difference between the current time 
       and the time given in days */
    $days = intval((time() - $time) / 86400);
    /* If some forward time is given return error */
    if($days < 0) {
        return -1;
    switch($days) {
        case 0: $_word = STRING_TODAY;
        case 1: $_word = STRING_YESTERDAY;
        case ($days >= 2 && $days <= 6): 
              $_word =  sprintf(STRING_DAYS, $days);
        case ($days >= 7 && $days < 14): 
              $_word= STRING_WEEK;
        case ($days >= 14 && $days <= 365): 
              $_word =  sprintf(STRING_WEEKS, intval($days / 7));
        default : return date(DATE_FORMAT, $time);
    return $_word;

Hope someone finds this useful.


11 thoughts on “Printing relative dates in php

  1. If I may make a suggestion, maybe sprintf should be used instead of concatenating strings. Basically, you would define STRING_DAYS, HOURS and WEEKS so, that you can use a sprintf placeholder. This way the relative position of the number with the text isn’t locked down, like it is now locked down to only allow text after the number.

  2. Instead of polluting the global space with DEFINEs what you could do is use CONSTs instead from within the class – where they belong IMHO…

    Makes the code more portable if for example, you move to another application? If you have a brain (and I feel that you do) then use it 🙂

  3. Yes they would belong in a class, but I’ve not defined a class here, it is a function. And it would be a bad idea to put the constants in the function. If someone wanted to change the string format he would have to dig into the function to change it. Better to use ‘define’ and save it into a language or config file. And anyways in such kind of issues you can argue from any direction, so it all depends on yours tastes.
    – p.s The last time I checked I had a brain, but who knows, maybe I’m a zombie contributing something to the world, however small, instead of sitting on my butt and passing smartass remarks. 🙂

  4. That’s a clever implementation, simple and readable. I’ll probably be using that function for my own projects, possibly in a class/object oriented fashion. Thanks for sharing this.

Comments are closed.