285

I am trying to convert a timestamp of the format 2009-09-12 20:57:19 and turn it into something like 3 minutes ago with PHP.

I found a useful script to do this, but I think it's looking for a different format to be used as the time variable. The script I'm wanting to modify to work with this format is:

function _ago($tm,$rcs = 0) {
    $cur_tm = time(); 
    $dif = $cur_tm-$tm;
    $pds = array('second','minute','hour','day','week','month','year','decade');
    $lngh = array(1,60,3600,86400,604800,2630880,31570560,315705600);

    for($v = sizeof($lngh)-1; ($v >= 0)&&(($no = $dif/$lngh[$v])<=1); $v--); if($v < 0) $v = 0; $_tm = $cur_tm-($dif%$lngh[$v]);
        $no = floor($no);
        if($no <> 1)
            $pds[$v] .='s';
        $x = sprintf("%d %s ",$no,$pds[$v]);
        if(($rcs == 1)&&($v >= 1)&&(($cur_tm-$_tm) > 0))
            $x .= time_ago($_tm);
        return $x;
    }

I think on those first few lines the script is trying to do something that looks like this (different date format math):

$dif = 1252809479 - 2009-09-12 20:57:19;

How would I go about converting my timestamp into that (unix?) format?

lorem monkey
  • 3,942
  • 3
  • 35
  • 49
willdanceforfun
  • 11,044
  • 31
  • 82
  • 122
  • possible duplicate of [How to calculate the difference between two dates using PHP?](http://stackoverflow.com/questions/676824/how-to-calculate-the-difference-between-two-dates-using-php) – Glavić Sep 18 '13 at 02:38
  • PHP & jQuery example here http://www.freakyjolly.com/convert-date-time-to-facebook-style/ – Code Spy Jun 04 '18 at 11:48

32 Answers32

561

Use example :

echo time_elapsed_string('2013-05-01 00:22:35');
echo time_elapsed_string('@1367367755'); # timestamp input
echo time_elapsed_string('2013-05-01 00:22:35', true);

Input can be any supported date and time format.

Output :

4 months ago
4 months ago
4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago

Function :

function time_elapsed_string($datetime, $full = false) {
    $now = new DateTime;
    $ago = new DateTime($datetime);
    $diff = $now->diff($ago);

    $diff->w = floor($diff->d / 7);
    $diff->d -= $diff->w * 7;

    $string = array(
        'y' => 'year',
        'm' => 'month',
        'w' => 'week',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second',
    );
    foreach ($string as $k => &$v) {
        if ($diff->$k) {
            $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
        } else {
            unset($string[$k]);
        }
    }

    if (!$full) $string = array_slice($string, 0, 1);
    return $string ? implode(', ', $string) . ' ago' : 'just now';
}
mahen3d
  • 7,047
  • 13
  • 51
  • 103
Glavić
  • 42,781
  • 13
  • 77
  • 107
  • 2
    The week part is nice but overall the function should be more flexible (`$full` should be a string input to filter the output as needed). e.g. `time_elapsed_string($datetime, $format = "ymw")`. P.S. Flat version: http://stackoverflow.com/a/5010169/318765 – mgutt Jan 28 '14 at 12:19
  • 20
    Regarding my last comment: Change `$full = false` to `$level = 7` and `if (!$full) $string = array_slice($string, 0, 1);` to `$string = array_slice($string, 0, $level);` and call `time_elapsed_string($datetime, 2)` to obtain only the two highest date strings. I think this shoud fit all needs. – mgutt Jan 28 '14 at 12:39
  • 1
    @mgutt: ofc this function will not work for any-case-user-wants-scenario; but it is a nice starting point, where you can, with minimal fix, get what you need, like you already demonstrated... – Glavić Jan 28 '14 at 13:12
  • 2
    I'm getting `Unknown property (w)` at this line `$diff->w = floor($diff->d / 7);` – vonUbisch Jun 30 '15 at 11:14
  • 1
    @vonUbisch: are you using PHP version 5.3.0 - 5.3.5? If you do, upgrade it :D or slightly modify the function. – Glavić Jun 30 '15 at 13:45
  • True, 5.3.1 to be exact, thanks for the explanation. – vonUbisch Jul 01 '15 at 07:11
  • @Glavić: good work. better show timago for 3 days after 3 days date show in normal like: 01/01/2015. ie: stackoverflow work with this method and after X days show full date. can u edit u answer?! – Perspolis Jul 12 '15 at 19:05
  • @Perspolis: why would I modify this function? Don't even call this function if date is older that 3 days. – Glavić Jul 12 '15 at 20:08
  • 3
    To fix this issue `Unknown property (w)` issue in PHP5.3 and below, convert $diff from an object into an array and adjust the rest of the code accordingly. I have the fix posted here: http://stackoverflow.com/a/32723846/235633 – bafromca Sep 22 '15 at 23:54
  • you might wanna add a ``if(!$datetime) { return 'never'; }`` if you use it to display login times – Jörn Berkefeld Feb 18 '16 at 09:47
  • @JörnBerkefeld: for you maybe this works, for others not. Everyone has a possibility to modify the function in there project. Here is best to keep function as clean as possible. – Glavić Feb 18 '16 at 09:50
  • I totally agree! hence the comment with an "if" and not an edit of your answer which I originally started ;-) – Jörn Berkefeld Feb 18 '16 at 09:51
  • I test this.Best solution.Thank you dear... . Your foreach loop will run only 7 times and not heavy process. It's good. – Milad Ghiravani May 09 '16 at 09:06
  • `$string ? implode(', ', $string) . ($diff->invert ? ' ago' : '') : 'just now';` if use feature time the use `$diff->invert` – dlarchikov Sep 26 '16 at 17:40
  • 1
    @AbhijitKumbhar: 2nd parameter of `DateTime` is timezone. [example](https://eval.in/663054) – Glavić Oct 19 '16 at 10:17
  • Whenever you use a parameter by reference in a for loop, &$v, you should unset it when you are done to prevent unexpected behavior. After your for loop, unset( $v ); – Saeven Dec 06 '16 at 21:25
  • @Saeven: there is no unexpected behavior when you know what you are doing. Since variable $v is not used anywhere else in the function, you do not need to unset it... – Glavić Dec 07 '16 at 07:38
  • @Glavić it was a general comment for anyone who runs across this. Internally, I never merge PRs that contain references in for loops. There's always a way to do without it. Good post here: http://schlueters.de/blog/archives/141-References-and-foreach.html – Saeven Dec 07 '16 at 16:49
  • It doesn't work for me. I use a NOW() date and it shows me 2 hours ago – paulalexandru May 09 '17 at 20:29
  • @paulalexandru: like you figure out, you had timezone issues. This function could be modified so `DateTime` accepts 2nd parameter, which is timezone. – Glavić May 15 '17 at 14:48
  • Well you better customize the function or leave the note I added otherwise if somebody will have this issue, he might get stuck. Thanks – paulalexandru May 15 '17 at 16:49
  • @paulalexandru: there are thousand issues with timezones on SO. If I would add every request to this function, it would be 500 lines long. Let's make function simple, and every1 can modify it to suit there needs. On other hand; I would not use global setting to set timezone, like you proposed. I would rather do in like this: https://eval.in/796995 – Glavić May 16 '17 at 12:31
  • nice , thanks for this code.but i am getting few differences in time with my database datetime value.can you help me out? – rahul singh Jul 21 '17 at 20:25
  • @rahulsingh: you probably have timezone issues. What is your default timezone? And in what format is your datetime input? – Glavić Jul 22 '17 at 05:12
  • @xamDev: your problem has nothing to do with this function; you are mixing AM and PM, or you don't understand date format. Check how compound formats are parsed: http://php.net/manual/en/datetime.formats.php – Glavić Jan 09 '18 at 09:53
  • what if i want the reverse! i mean i give `5 years, 9 months, 1 week, 5 days, 22 hours ago ` and i want to get `2013-05-01 00:22:01` .. is it possible! – Reham Fahmy Feb 13 '19 at 22:44
  • @Glavić: in the current solution the plurality is defined as + 's' (which is fine in English)... but what to do if you want to change this logic manually for each time unit? So for example in Dutch year = jaar and years = jaren, month = maand and months = maanden, week = week and weeks = weken. – Yoorizz May 26 '20 at 15:09
  • try this and with yours https://stackoverflow.com/a/62267046/1331294 – Monzur Jun 11 '20 at 04:02
  • @Monzur: Sorry, this is the wrong approach. You are saying that code shows wrong, and you are not willing to back up that up with nothing, not even with description of what is showing wrong. Please show me an example of my code not working, and I will tell you what is that. – Glavić Jun 11 '20 at 14:48
  • Thanks for the code example but I need only seconds, minutes, hours and days, nothing more. Can you help me please? – borkafight Jul 20 '20 at 11:20
  • if you need to round up: `$diff = $now->diff($ago); if(!$full){ if($diff->s > 30) $diff->i++; if($diff->i > 30) $diff->h++; if($diff->h > 12) $diff->d++; if($diff->d > 15) $diff->m++; if($diff->m > 6) $diff->y++; if($diff->i === 60) $diff->i = 0; if($diff->h === 24) $diff->h = 0; } $diff->w = floor($diff->d / 7); ` – Arthur Shlain Nov 25 '20 at 11:49
  • Thanks, it will also convert MySQL DATETIME to time ago functionality – shaz3e Apr 17 '21 at 16:00
  • Is this recommended to use in 2021? I still upvote this question – Posandu Nov 06 '21 at 14:40
  • 1
    @ŕ̷͉ge̸ḓ̶̅i̷t still :D – Glavić Nov 06 '21 at 18:37
  • `Deprecated: Creation of dynamic property DateInterval::$w is deprecated` I dont know how to fix https://stackoverflow.com/questions/74588589/php-datetime-deprecated-creation-of-dynamic-property-dateintervalw-is-depr – Anas Fanani Nov 27 '22 at 08:40
105
function time_elapsed_string($ptime)
{
    $etime = time() - $ptime;

    if ($etime < 1)
    {
        return '0 seconds';
    }

    $a = array( 365 * 24 * 60 * 60  =>  'year',
                 30 * 24 * 60 * 60  =>  'month',
                      24 * 60 * 60  =>  'day',
                           60 * 60  =>  'hour',
                                60  =>  'minute',
                                 1  =>  'second'
                );
    $a_plural = array( 'year'   => 'years',
                       'month'  => 'months',
                       'day'    => 'days',
                       'hour'   => 'hours',
                       'minute' => 'minutes',
                       'second' => 'seconds'
                );

    foreach ($a as $secs => $str)
    {
        $d = $etime / $secs;
        if ($d >= 1)
        {
            $r = round($d);
            return $r . ' ' . ($r > 1 ? $a_plural[$str] : $str) . ' ago';
        }
    }
}
Pablo
  • 1
  • 2
Ayman Hussein
  • 3,817
  • 7
  • 28
  • 48
  • 75
    This is not good solution, since it is using `30days for month`, and `12x30days for year`, and because of that it will return invalid number of years bellow year <= 1978. [Example](https://eval.in/51929) where it returns 39 years, but it should 38. And it also doesn't work for years bellow 1970. – Glavić Oct 02 '13 at 12:33
  • 47
    Terrible solution. Why does this have 42 upvotes and selected answer? Since when does every month have 30 days? – BadHorsie Mar 14 '14 at 17:22
  • @Ayman Hussein, it gives me this error: `Fatal error: time_elapsed_string(): Unknown property (w) in` – ThePixelPony Oct 02 '14 at 15:08
  • 5
    @wassimboy, could you please tell me why you want to down vote my answer. if my answer is not good enough you can write a comment to correct it without down vote. – Ayman Hussein Oct 22 '14 at 09:15
  • 8
    Your answer is not good because it counts 30 days per month and not all months have 30 days. Read the other comments above. – Tomas Gonzalez Nov 04 '14 at 18:47
  • 1
    @Glavić what is your opinion about [this](http://stackoverflow.com/questions/2915864/php-how-to-find-the-time-elapsed-since-a-date-time) ? – Shafizadeh Aug 09 '15 at 16:06
  • 13
    This is a function to return a general phrase, like "roughly how long ago was this comment made"? It is not precise and has some downfalls, as mentioned above, but for dates in the near past (say 30 years near past and less) it give us non-precise humans an idea how long ago an event occurred. Worked well for my application. – Tim Dearborn Sep 27 '15 at 13:17
  • 1
    What should be the proper format for `ptime` ? second ? big int ? mySQL timestamp ? Can some one please clarify that ? Thanks. – code-8 Nov 30 '15 at 15:53
  • 1
    Chill out. World will be doomed when it'll show inccorrect number of years of today's dates ;) – Adam Pietrasiak Dec 08 '16 at 13:14
  • This is a great solution, and an elegant solution. This type of script is usually used to show how much time has past (in general terms) since something happened. It doesn't need to be precise. One year is now calculated as "365 * 24 * 60 * 60" which works well. +1 Vote – SW_Cali Oct 20 '21 at 09:49
35
$time_elapsed = timeAgo($time_ago); //The argument $time_ago is in timestamp (Y-m-d H:i:s)format.

//Function definition

function timeAgo($time_ago)
{
    $time_ago = strtotime($time_ago);
    $cur_time   = time();
    $time_elapsed   = $cur_time - $time_ago;
    $seconds    = $time_elapsed ;
    $minutes    = round($time_elapsed / 60 );
    $hours      = round($time_elapsed / 3600);
    $days       = round($time_elapsed / 86400 );
    $weeks      = round($time_elapsed / 604800);
    $months     = round($time_elapsed / 2600640 );
    $years      = round($time_elapsed / 31207680 );
    // Seconds
    if($seconds <= 60){
        return "just now";
    }
    //Minutes
    else if($minutes <=60){
        if($minutes==1){
            return "one minute ago";
        }
        else{
            return "$minutes minutes ago";
        }
    }
    //Hours
    else if($hours <=24){
        if($hours==1){
            return "an hour ago";
        }else{
            return "$hours hrs ago";
        }
    }
    //Days
    else if($days <= 7){
        if($days==1){
            return "yesterday";
        }else{
            return "$days days ago";
        }
    }
    //Weeks
    else if($weeks <= 4.3){
        if($weeks==1){
            return "a week ago";
        }else{
            return "$weeks weeks ago";
        }
    }
    //Months
    else if($months <=12){
        if($months==1){
            return "a month ago";
        }else{
            return "$months months ago";
        }
    }
    //Years
    else{
        if($years==1){
            return "one year ago";
        }else{
            return "$years years ago";
        }
    }
}
disco crazy
  • 31,313
  • 12
  • 80
  • 83
Captain Red
  • 1,171
  • 2
  • 16
  • 27
35

I don't know why nobody mention Carbon yet.

https://github.com/briannesbitt/Carbon

This is actually an extension to php dateTime (which was already used here) and it has: diffForHumans method. So all you need to do is:

$dt = Carbon::parse('2012-9-5 23:26:11.123789');
echo $dt->diffForHumans();

more examples: http://carbon.nesbot.com/docs/#api-humandiff

Pros of this solution:

  • it works for future dates and will return something like in 2 months etc.
  • you can use localization to get other languages and the pluralization works fine
  • if you will start using Carbon for other things working with dates will be as easy as never.
29

This is actually a better solution I've found. Uses jQuery however it works perfectly. Also it refreshes automatically similar to the way SO and Facebook does so you don't have to refresh the page to see the updates.

This plugin will read your datetime attr in the <time> tag and fill it in for you.

e.g. "4 minutes ago" or "about 1 day ago

http://timeago.yarp.com/

Panama Jack
  • 24,158
  • 10
  • 63
  • 95
11

I found results like the following ugly:

1 years, 2 months, 0 days, 0 hours, 53 minutes and 1 seconds

Because of that I realized a function that respects plurals, removes empty values and optionally it is possible to shorten the output:

function since($timestamp, $level=6) {
    global $lang;
    $date = new DateTime();
    $date->setTimestamp($timestamp);
    $date = $date->diff(new DateTime());
    // build array
    $since = array_combine(array('year', 'month', 'day', 'hour', 'minute', 'second'), explode(',', $date->format('%y,%m,%d,%h,%i,%s')));
    // remove empty date values
    $since = array_filter($since);
    // output only the first x date values
    $since = array_slice($since, 0, $level);
    // build string
    $last_key = key(array_slice($since, -1, 1, true));
    $string = '';
    foreach ($since as $key => $val) {
        // separator
        if ($string) {
            $string .= $key != $last_key ? ', ' : ' ' . $lang['and'] . ' ';
        }
        // set plural
        $key .= $val > 1 ? 's' : '';
        // add date value
        $string .= $val . ' ' . $lang[ $key ];
    }
    return $string;
}

Looks much better:

1 year, 2 months, 53 minutes and 1 second

Optionally use $level = 2 to shorten it as follows:

1 year and 2 months

Remove the $lang part if you need it only in English or edit this translation to fit your needs:

$lang = array(
    'second' => 'Sekunde',
    'seconds' => 'Sekunden',
    'minute' => 'Minute',
    'minutes' => 'Minuten',
    'hour' => 'Stunde',
    'hours' => 'Stunden',
    'day' => 'Tag',
    'days' => 'Tage',
    'month' => 'Monat',
    'months' => 'Monate',
    'year' => 'Jahr',
    'years' => 'Jahre',
    'and' => 'und',
);
mgutt
  • 5,867
  • 2
  • 50
  • 77
  • Of all, this one works well for me. Although it does not show to go or ago, but works both ways. Easy fix: if ($date->invert > 0) { $ending = " to go"; } else { $ending = " ago"; } Just add $ending to the $string. – Quentin Campbell Apr 18 '18 at 14:48
  • Use of json functions here is a big performance hit and entirely unnecessary. This is not a good solution. – zombat Jun 25 '19 at 20:13
  • @zombat Thank you for your feedback. I changed the line against `explode` and `array_combine`. – mgutt Jun 26 '19 at 21:28
  • Why `global`? Read some www.PhpTheRightWay.com please. – AlexioVay Feb 01 '21 at 18:48
10
function humanTiming ($time)
        {

            $time = time() - $time; // to get the time since that moment
            $time = ($time<1)? 1 : $time;
            $tokens = array (
                31536000 => 'year',
                2592000 => 'month',
                604800 => 'week',
                86400 => 'day',
                3600 => 'hour',
                60 => 'minute',
                1 => 'second'
            );

            foreach ($tokens as $unit => $text) {
                if ($time < $unit) continue;
                $numberOfUnits = floor($time / $unit);
                return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
            }

        }

echo humanTiming( strtotime($mytimestring) );
brycejl
  • 1,411
  • 17
  • 22
  • 1
    This is really great. Thank you for sharing. But there are instances where the function returns $numberOfUnits empty and it just outputs "ago". Seemingly because the value is less than 1 second. In that instance if you could make it default to something like "just now" this would be perfect. – Hezerac Sep 27 '16 at 21:31
6

i made this and it's working just fine it's working for both unix timestamp like 1470919932 or formatted time like 16-08-11 14:53:30

function timeAgo($time_ago) {
    $time_ago =  strtotime($time_ago) ? strtotime($time_ago) : $time_ago;
    $time  = time() - $time_ago;

switch($time):
// seconds
case $time <= 60;
return 'lessthan a minute ago';
// minutes
case $time >= 60 && $time < 3600;
return (round($time/60) == 1) ? 'a minute' : round($time/60).' minutes ago';
// hours
case $time >= 3600 && $time < 86400;
return (round($time/3600) == 1) ? 'a hour ago' : round($time/3600).' hours ago';
// days
case $time >= 86400 && $time < 604800;
return (round($time/86400) == 1) ? 'a day ago' : round($time/86400).' days ago';
// weeks
case $time >= 604800 && $time < 2600640;
return (round($time/604800) == 1) ? 'a week ago' : round($time/604800).' weeks ago';
// months
case $time >= 2600640 && $time < 31207680;
return (round($time/2600640) == 1) ? 'a month ago' : round($time/2600640).' months ago';
// years
case $time >= 31207680;
return (round($time/31207680) == 1) ? 'a year ago' : round($time/31207680).' years ago' ;

endswitch;
}

?>
Ahmad ghoneim
  • 844
  • 7
  • 13
5

I modified the original function a bit to be (in my opinion more useful, or logical).

// display "X time" ago, $rcs is precision depth
function time_ago ($tm, $rcs = 0) {
  $cur_tm = time(); 
  $dif = $cur_tm - $tm;
  $pds = array('second','minute','hour','day','week','month','year','decade');
  $lngh = array(1,60,3600,86400,604800,2630880,31570560,315705600);

  for ($v = count($lngh) - 1; ($v >= 0) && (($no = $dif / $lngh[$v]) <= 1); $v--);
    if ($v < 0)
      $v = 0;
  $_tm = $cur_tm - ($dif % $lngh[$v]);

  $no = ($rcs ? floor($no) : round($no)); // if last denomination, round

  if ($no != 1)
    $pds[$v] .= 's';
  $x = $no . ' ' . $pds[$v];

  if (($rcs > 0) && ($v >= 1))
    $x .= ' ' . $this->time_ago($_tm, $rcs - 1);

  return $x;
}
Bobb Fwed
  • 317
  • 3
  • 6
  • 1
    Any function that uses math based on a fixed calendar is fundamentally flawed. Use the Date object, don't do math with time. – Chris Baker Sep 13 '14 at 00:42
  • 2
    @chris-baker When most people use these types of functions, precision to the second is not necessary. The function is accurate over short periods of time, and over long periods of time, being close is more than good enough. – Bobb Fwed Jul 28 '16 at 17:46
5

I usually use this to find out difference between current and passed datetime stamp

OUTPUT

//If difference is greater than 7 days
7 June 2019

// if difference is greater than 24 hours and less than 7 days
1 days ago
6 days ago

1 hour ago
23 hours ago

1 minute ago
58 minutes ago

1 second ago
20 seconds ago

CODE

//return current date time
function getCurrentDateTime(){
    //date_default_timezone_set("Asia/Calcutta");
    return date("Y-m-d H:i:s");
}
function getDateString($date){
    $dateArray = date_parse_from_format('Y/m/d', $date);
    $monthName = DateTime::createFromFormat('!m', $dateArray['month'])->format('F');
    return $dateArray['day'] . " " . $monthName  . " " . $dateArray['year'];
}

function getDateTimeDifferenceString($datetime){
    $currentDateTime = new DateTime(getCurrentDateTime());
    $passedDateTime = new DateTime($datetime);
    $interval = $currentDateTime->diff($passedDateTime);
    //$elapsed = $interval->format('%y years %m months %a days %h hours %i minutes %s seconds');
    $day = $interval->format('%a');
    $hour = $interval->format('%h');
    $min = $interval->format('%i');
    $seconds = $interval->format('%s');

    if($day > 7)
        return getDateString($datetime);
    else if($day >= 1 && $day <= 7 ){
        if($day == 1) return $day . " day ago";
        return $day . " days ago";
    }else if($hour >= 1 && $hour <= 24){
        if($hour == 1) return $hour . " hour ago";
        return $hour . " hours ago";
    }else if($min >= 1 && $min <= 60){
        if($min == 1) return $min . " minute ago";
        return $min . " minutes ago";
    }else if($seconds >= 1 && $seconds <= 60){
        if($seconds == 1) return $seconds . " second ago";
        return $seconds . " seconds ago";
    }
}
Vicky Salunkhe
  • 9,869
  • 6
  • 42
  • 59
  • Thanks for this. I actually converted it to C# code. – Darrel K. Apr 30 '20 at 05:59
  • Undefined function getCurrentDateTime() fyi – RicardO May 01 '20 at 14:58
  • @gfivehost added the function code, you can check it now. – Vicky Salunkhe May 01 '20 at 17:03
  • i really like this snippet. but DateTime does not support locale settings to have translated datetime formarts like name of the days or months. eg in getDateString() format('F') is english only. A switch to IntlDateFormatter and gettext() for the custom output during the first 7 days will solve this for i18n – f b Dec 17 '21 at 09:48
4

Just to throw in another option...

Whilst I prefer the DateTime method posting here, I didn't like the fact it displayed 0 years etc.

/* 
 * Returns a string stating how long ago this happened
 */

private function timeElapsedString($ptime){
    $diff = time() - $ptime;
    $calc_times = array();
    $timeleft   = array();

    // Prepare array, depending on the output we want to get.
    $calc_times[] = array('Year',   'Years',   31557600);
    $calc_times[] = array('Month',  'Months',  2592000);
    $calc_times[] = array('Day',    'Days',    86400);
    $calc_times[] = array('Hour',   'Hours',   3600);
    $calc_times[] = array('Minute', 'Minutes', 60);
    $calc_times[] = array('Second', 'Seconds', 1);

    foreach ($calc_times AS $timedata){
        list($time_sing, $time_plur, $offset) = $timedata;

        if ($diff >= $offset){
            $left = floor($diff / $offset);
            $diff -= ($left * $offset);
            $timeleft[] = "{$left} " . ($left == 1 ? $time_sing : $time_plur);
        }
    }

    return $timeleft ? (time() > $ptime ? null : '-') . implode(' ', $timeleft) : 0;
}
Community
  • 1
  • 1
TMH
  • 6,096
  • 7
  • 51
  • 88
4

To directly answer the question... you can use...

strtotime()

https://www.php.net/manual/en/function.strtotime.php

$dif = time() - strtotime("2009-09-12 20:57:19");

E.G:

echo round(((( time() - strtotime("2021-08-01 21:57:50") )/60)/60)/24).' day(s) ago';

Result: 1 day(s) ago

Dazza
  • 126
  • 7
2

it help you check it

   function calculate_time_span($seconds)
{  
 $year = floor($seconds /31556926);
$months = floor($seconds /2629743);
$week=floor($seconds /604800);
$day = floor($seconds /86400); 
$hours = floor($seconds / 3600);
 $mins = floor(($seconds - ($hours*3600)) / 60); 
$secs = floor($seconds % 60);
 if($seconds < 60) $time = $secs." seconds ago";
 else if($seconds < 3600 ) $time =($mins==1)?$mins."now":$mins." mins ago";
 else if($seconds < 86400) $time = ($hours==1)?$hours." hour ago":$hours." hours ago";
 else if($seconds < 604800) $time = ($day==1)?$day." day ago":$day." days ago";
 else if($seconds < 2629743) $time = ($week==1)?$week." week ago":$week." weeks ago";
 else if($seconds < 31556926) $time =($months==1)? $months." month ago":$months." months ago";
 else $time = ($year==1)? $year." year ago":$year." years ago";
return $time; 
}  
  $seconds = time() - strtotime($post->post_date); 
echo calculate_time_span($seconds); 
Abbbas khan
  • 306
  • 2
  • 15
2

Try this, I found it from my old codes, which shows the correct Result

function ago($datefrom, $dateto = -1) {
    // Defaults and assume if 0 is passed in that
    // its an error rather than the epoch

    if ($datefrom == 0) {
        return "A long time ago";
    }
    if ($dateto == -1) {
        $dateto = time();
    }

    // Make the entered date into Unix timestamp from MySQL datetime field

    $datefrom = strtotime($datefrom);

    // Calculate the difference in seconds betweeen
    // the two timestamps

    $difference = $dateto - $datefrom;

    // Based on the interval, determine the
    // number of units between the two dates
    // From this point on, you would be hard
    // pushed telling the difference between
    // this function and DateDiff. If the $datediff
    // returned is 1, be sure to return the singular
    // of the unit, e.g. 'day' rather 'days'

    switch (true) {
        // If difference is less than 60 seconds,
        // seconds is a good interval of choice
        case(strtotime('-1 min', $dateto) < $datefrom):
            $datediff = $difference;
            $res = ($datediff == 1) ? $datediff . ' second' : $datediff . ' seconds';
            break;
        // If difference is between 60 seconds and
        // 60 minutes, minutes is a good interval
        case(strtotime('-1 hour', $dateto) < $datefrom):
            $datediff = floor($difference / 60);
            $res = ($datediff == 1) ? $datediff . ' minute' : $datediff . ' minutes';
            break;
        // If difference is between 1 hour and 24 hours
        // hours is a good interval
        case(strtotime('-1 day', $dateto) < $datefrom):
            $datediff = floor($difference / 60 / 60);
            $res = ($datediff == 1) ? $datediff . ' hour' : $datediff . ' hours';
            break;
        // If difference is between 1 day and 7 days
        // days is a good interval                
        case(strtotime('-1 week', $dateto) < $datefrom):
            $day_difference = 1;
            while (strtotime('-' . $day_difference . ' day', $dateto) >= $datefrom) {
                $day_difference++;
            }

            $datediff = $day_difference;
            $res = ($datediff == 1) ? 'yesterday' : $datediff . ' days';
            break;
        // If difference is between 1 week and 30 days
        // weeks is a good interval            
        case(strtotime('-1 month', $dateto) < $datefrom):
            $week_difference = 1;
            while (strtotime('-' . $week_difference . ' week', $dateto) >= $datefrom) {
                $week_difference++;
            }

            $datediff = $week_difference;
            $res = ($datediff == 1) ? 'last week' : $datediff . ' weeks';
            break;
        // If difference is between 30 days and 365 days
        // months is a good interval, again, the same thing
        // applies, if the 29th February happens to exist
        // between your 2 dates, the function will return
        // the 'incorrect' value for a day
        case(strtotime('-1 year', $dateto) < $datefrom):
            $months_difference = 1;
            while (strtotime('-' . $months_difference . ' month', $dateto) >= $datefrom) {
                $months_difference++;
            }

            $datediff = $months_difference;
            $res = ($datediff == 1) ? $datediff . ' month' : $datediff . ' months';

            break;
        // If difference is greater than or equal to 365
        // days, return year. This will be incorrect if
        // for example, you call the function on the 28th April
        // 2008 passing in 29th April 2007. It will return
        // 1 year ago when in actual fact (yawn!) not quite
        // a year has gone by
        case(strtotime('-1 year', $dateto) >= $datefrom):
            $year_difference = 1;
            while (strtotime('-' . $year_difference . ' year', $dateto) >= $datefrom) {
                $year_difference++;
            }

            $datediff = $year_difference;
            $res = ($datediff == 1) ? $datediff . ' year' : $datediff . ' years';
            break;
    }
    return $res;
}

Example: echo ago('2020-06-03 00:14:21 AM');

Output: 6 days

Monzur
  • 1,341
  • 14
  • 11
1

I'm aware that there are several answers here, but this is what I came up with. This only handles MySQL DATETIME values as per the original question I was responding to. The array $a needs some work. I welcome comments on how to improve. Call as:

echo time_elapsed_string('2014-11-14 09:42:28');

function time_elapsed_string($ptime)
{
    // Past time as MySQL DATETIME value
    $ptime = strtotime($ptime);

    // Current time as MySQL DATETIME value
    $csqltime = date('Y-m-d H:i:s');

    // Current time as Unix timestamp
    $ctime = strtotime($csqltime); 

    // Elapsed time
    $etime = $ctime - $ptime;

    // If no elapsed time, return 0
    if ($etime < 1){
        return '0 seconds';
    }

    $a = array( 365 * 24 * 60 * 60  =>  'year',
                 30 * 24 * 60 * 60  =>  'month',
                      24 * 60 * 60  =>  'day',
                           60 * 60  =>  'hour',
                                60  =>  'minute',
                                 1  =>  'second'
    );

    $a_plural = array( 'year'   => 'years',
                       'month'  => 'months',
                       'day'    => 'days',
                       'hour'   => 'hours',
                       'minute' => 'minutes',
                       'second' => 'seconds'
    );

    foreach ($a as $secs => $str){
        // Divide elapsed time by seconds
        $d = $etime / $secs;
        if ($d >= 1){
            // Round to the next lowest integer 
            $r = floor($d);
            // Calculate time to remove from elapsed time
            $rtime = $r * $secs;
            // Recalculate and store elapsed time for next loop
            if(($etime - $rtime)  < 0){
                $etime -= ($r - 1) * $secs;
            }
            else{
                $etime -= $rtime;
            }
            // Create string to return
            $estring = $estring . $r . ' ' . ($r > 1 ? $a_plural[$str] : $str) . ' ';
        }
    }
    return $estring . ' ago';
}
rdpcoder
  • 100
  • 9
1

I tried this and works fine for me

$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-10');
$difference = $datetime1->diff($datetime2);
echo formatOutput($difference);

function formatOutput($diff){
    /* function to return the highrst defference fount */
    if(!is_object($diff)){
        return;
    }

    if($diff->y > 0){
        return $diff->y .(" year".($diff->y > 1?"s":"")." ago");
    }

    if($diff->m > 0){
        return $diff->m .(" month".($diff->m > 1?"s":"")." ago");
    }

    if($diff->d > 0){
        return $diff->d .(" day".($diff->d > 1?"s":"")." ago");
    }

    if($diff->h > 0){
        return $diff->h .(" hour".($diff->h > 1?"s":"")." ago");
    }

    if($diff->i > 0){
        return $diff->i .(" minute".($diff->i > 1?"s":"")." ago");
    }

    if($diff->s > 0){
        return $diff->s .(" second".($diff->s > 1?"s":"")." ago");
    }
}

Check this link for reference here

Thanks! and have fun.

Ruberandinda Patience
  • 3,435
  • 3
  • 20
  • 18
1

This is what I went with. Its a modified version of Abbbas khan's post:

<?php

  function calculate_time_span($post_time)
  {  
  $seconds = time() - strtotime($post);
  $year = floor($seconds /31556926);
  $months = floor($seconds /2629743);
  $week=floor($seconds /604800);
  $day = floor($seconds /86400); 
  $hours = floor($seconds / 3600);
  $mins = floor(($seconds - ($hours*3600)) / 60); 
  $secs = floor($seconds % 60);
  if($seconds < 60) $time = $secs." seconds ago";
  else if($seconds < 3600 ) $time =($mins==1)?$mins."now":$mins." mins ago";
  else if($seconds < 86400) $time = ($hours==1)?$hours." hour ago":$hours." hours ago";
  else if($seconds < 604800) $time = ($day==1)?$day." day ago":$day." days ago";
  else if($seconds < 2629743) $time = ($week==1)?$week." week ago":$week." weeks ago";
  else if($seconds < 31556926) $time =($months==1)? $months." month ago":$months." months ago";
  else $time = ($year==1)? $year." year ago":$year." years ago";
  return $time; 
  }  



 // uses
 // $post_time="2017-12-05 02:05:12";
 // echo calculate_time_span($post_time); 
drtechno
  • 298
  • 2
  • 9
1

Many solutions here did not account for rounding. For example:

Event happened at 3pm two days ago. If you are checking at 2pm, it will show one day ago. If you are checking at 4pm it will show two days ago.

If you are working with unix time, this helps:

// how long since event has passed in seconds
$secs = time() - $time_ago;

// how many seconds in a day
$sec_per_day = 60*60*24;

// days elapsed
$days_elapsed = floor($secs / $sec_per_day);

// how many seconds passed today
$today_seconds = date('G')*3600 + date('i') * 60 + date('s');

// how many seconds passed in the final day calculation
$remain_seconds = $secs % $sec_per_day;

if($today_seconds < $remain_seconds)
{
    $days_elapsed++;
}

echo 'The event was '.$days_ago.' days ago.';

It is not perfect if you are worried about leap seconds and daylight savings time.

Frank Forte
  • 2,031
  • 20
  • 19
1

I wanted to have dutch version that supported singles and plurals. Just adding an 's' at the end would not suffice, we use completely different words so I rewrote the top answer of this post.

This will result in:

2 jaren 1 maand 2 weken 1 dag 1 minuten 2 seconden

or

1 jaar 2 maanden 1 week 2 dagen 1 minuut 1 seconde

    public function getTimeAgo($full = false){

    $now = new \DateTime;
    $ago = new \DateTime($this->datetime());
    $diff = $now->diff($ago);

    $diff->w = floor($diff->d / 7);
    $diff->d -= $diff->w * 7;

    $string = array(
        'y' => 'jaren',
        'm' => 'maanden',
        'w' => 'weken',
        'd' => 'dagen',
        'h' => 'uren',
        'i' => 'minuten',
        's' => 'seconden',
    );
    $singleString = array(
        'y' => 'jaar',
        'm' => 'maand',
        'w' => 'week',
        'd' => 'dag',
        'h' => 'uur',
        'i' => 'minuut',
        's' => 'seconde',
    );
    // M.O. 2022-02-11 I rewrote this function to support dutch singles and plurals. Added some docs for next programmer to break his brain :)
    // For each possible notation, if corresponding value of current key is true (>1) otherwise remove its key/value from array
    // If the value from current key is 1, use value from $singleString array. Otherwise use value from $string array
    foreach ($string as $k => &$v) {
        if ($diff->$k) {
            if($diff->$k == 1){
                $v = $diff->$k . ' ' . $singleString[$k];
            } else {
                $v = $diff->$k . ' ' . $v;
            }
        } else {
            if($diff->$k == 1){
                unset($singleString[$k]);
            } else {
                unset($string[$k]);
            }
        }
    }

    // If $full = true, print all values.
    // Values have already been filtered with foreach removing keys that contain a 0 as value
    if (!$full) $string = array_slice($string, 0, 1);
    return $string ? implode(', ', $string) . '' : 'zojuist';
}

You should probably test it first because I am not that good of a programmer :)

Maarten
  • 402
  • 5
  • 20
0

You'll have to take each individual piece of your timestamp, and convert it into Unix time. For example for the timestamp, 2009-09-12 20:57:19.

(((2008-1970)*365)+(8*30)+12)*24+20 would give you a ROUGH estimate of the hours since January 1st, 1970.

Take that number, multiply by 60 and add 57 to get the minutes.

Take that, multiply by 60 and add 19.

That would convert it very roughly and inaccurately however.

Is there any reason you can't just take the normal Unix time to begin with?

LukeWarm74
  • 130
  • 1
  • 4
  • is it better to store as a unix time in the sql table? I'm using mysqls automatic timestamp update currently on a timestamp column (which can be changed to unix). I'm just learning what is better? – willdanceforfun Sep 13 '09 at 02:49
  • Definitely. I believe the default for a mySQL table is the type you referenced, but Unix time is far more practical. You can always store it as an int. – LukeWarm74 Sep 13 '09 at 02:55
  • Your database should have a function to convert the date to UNIX format. In mysql you use UNIX_TIMESTAMP(). Oh, and you should generally store your dates as DATETIMEs rather than INTs, so that you can use the sql functions for date manipulation. – CpnCrunch Sep 23 '13 at 20:43
  • You should never, ever use math on time. You're assuming a fixed calendar, which doesn't exist. Use the Date object provided in php to work with... dates. – Chris Baker Sep 13 '14 at 00:43
0

There is some issue with some language display time ago for example in Arabic there 3 needed formats to display date. I use this functions in my projects hopefully they can help someone (any suggestion or improvement I'll be apperciate :) )

/**
 *
 * @param   string $date1 
 * @param   string $date2 the date that you want to compare with $date1
 * @param   int $level  
 * @param   bool $absolute  
 */

function app_date_diff( $date1, $date2, $level = 3, $absolute = false ) {

    $date1 = date_create($date1);   
    $date2 = date_create($date2);
    $diff = date_diff( $date1, $date2, $absolute );

    $d = [
        'invert' => $diff->invert
    ];  

    $diffs = [
        'y' => $diff->y, 
        'm' => $diff->m, 
        'd' => $diff->d
    ];

    $level_reached = 0;

    foreach($diffs as $k=>$v) {

        if($level_reached >= $level) {
            break;
        }

        if($v > 0) {
            $d[$k] = $v;
            $level_reached++;
        }

    }

    return  $d;

}

/**
 * 
 */

function date_timestring( $periods, $format = 'latin', $separator = ',' ) {

    $formats = [
        'latin' => [
            'y' => ['year','years'],
            'm' => ['month','months'],
            'd' => ['day','days']
        ],
        'arabic' => [
            'y' => ['سنة','سنتين','سنوات'],
            'm' => ['شهر','شهرين','شهور'],
            'd' => ['يوم','يومين','أيام']
        ]
    ];

    $formats = $formats[$format];

    $string = [];

    foreach($periods as $period=>$value) {

        if(!isset($formats[$period])) {
            continue;
        }

        $string[$period] = $value.' ';
        if($format == 'arabic') {
            if($value == 2) {
                $string[$period] = $formats[$period][1];
            }elseif($value > 2 && $value <= 10) {
                $string[$period] .= $formats[$period][2];
            }else{
                $string[$period] .= $formats[$period][0];
            }

        }elseif($format == 'latin') {
            $string[$period] .= ($value > 1) ? $formats[$period][1] : $formats[$period][0];
        }

    }

    return implode($separator, $string);


}

function timeago( $date ) {

    $today = date('Y-m-d h:i:s');

    $diff = app_date_diff($date,$today,2);

    if($diff['invert'] == 1) {
        return '';
    }

    unset($diff[0]);

    $date_timestring = date_timestring($diff,'latin');

    return 'About '.$date_timestring;

}

$date1 = date('Y-m-d');
$date2 = '2018-05-14';

$diff = timeago($date2);
echo $diff;
Mourad Karoudi
  • 348
  • 3
  • 13
0

If you are using PostgreSQL then it will do the job for you:

const DT_SQL = <<<SQL
WITH lapse AS (SELECT (?::timestamp(0) - now()::timestamp(0))::text t)
SELECT CASE
  WHEN (select t from lapse) ~ '^\s*-' THEN replace((select t from lapse), '-', '') ||' ago' 
  ELSE (select t from lapse) END;
SQL;

function timeSpanText($ts, $conn)
// $ts: date-time string, $conn: PostgreSQL PDO connection
{
 return $conn -> prepare(DT_SQL) -> execute([ts]) -> fetchColumn();
}
Stefanov.sm
  • 11,215
  • 2
  • 21
  • 21
-1
$time_ago = ' ';
$time = time() - $time; // to get the time since that moment
$tokens = array (
31536000 => 'year',2592000 => 'month',604800 => 'week',86400 => 'day',3600 => 'hour',
60  => 'minute',1 => 'second');
foreach ($tokens as $unit => $text) {
if ($time < $unit)continue;
$numberOfUnits = floor($time / $unit);
$time_ago = ' '.$time_ago. $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'').'  ';
$time = $time % $unit;}echo $time_ago;
Mehreen Jamil
  • 34
  • 1
  • 6
-1

Here is my solution please check and modify according your requirements

function getHowLongAgo($date, $display = array('Year', 'Month', 'Day', 'Hour', 'Minute', 'Second'), $ago = '') {
        date_default_timezone_set('Australia/Sydney');
        $timestamp = strtotime($date);
        $timestamp = (int) $timestamp;
        $current_time = time();
        $diff = $current_time - $timestamp;

        //intervals in seconds
        $intervals = array(
            'year' => 31556926, 'month' => 2629744, 'week' => 604800, 'day' => 86400, 'hour' => 3600, 'minute' => 60
        );

        //now we just find the difference
        if ($diff == 0) {
            return ' Just now ';
        }

        if ($diff < 60) {
            return $diff == 1 ? $diff . ' second ago ' : $diff . ' seconds ago ';
        }

        if ($diff >= 60 && $diff < $intervals['hour']) {
            $diff = floor($diff / $intervals['minute']);
            return $diff == 1 ? $diff . ' minute ago ' : $diff . ' minutes ago ';
        }

        if ($diff >= $intervals['hour'] && $diff < $intervals['day']) {
            $diff = floor($diff / $intervals['hour']);
            return $diff == 1 ? $diff . ' hour ago ' : $diff . ' hours ago ';
        }

        if ($diff >= $intervals['day'] && $diff < $intervals['week']) {
            $diff = floor($diff / $intervals['day']);
            return $diff == 1 ? $diff . ' day ago ' : $diff . ' days ago ';
        }

        if ($diff >= $intervals['week'] && $diff < $intervals['month']) {
            $diff = floor($diff / $intervals['week']);
            return $diff == 1 ? $diff . ' week ago ' : $diff . ' weeks ago ';
        }

        if ($diff >= $intervals['month'] && $diff < $intervals['year']) {
            $diff = floor($diff / $intervals['month']);
            return $diff == 1 ? $diff . ' month ago ' : $diff . ' months ago ';
        }

        if ($diff >= $intervals['year']) {
            $diff = floor($diff / $intervals['year']);
            return $diff == 1 ? $diff . ' year ago ' : $diff . ' years ago ';
        }
    }

Thanks

Dineshaws
  • 2,065
  • 16
  • 26
-1
# This function prints the difference between two php datetime objects
# in a more human readable form
# inputs should be like strtotime($date)
function humanizeDateDiffference($now,$otherDate=null,$offset=null){
    if($otherDate != null){
        $offset = $now - $otherDate;
    }
    if($offset != null){
        $deltaS = $offset%60;
        $offset /= 60;
        $deltaM = $offset%60;
        $offset /= 60;
        $deltaH = $offset%24;
        $offset /= 24;
        $deltaD = ($offset > 1)?ceil($offset):$offset;      
    } else{
        throw new Exception("Must supply otherdate or offset (from now)");
    }
    if($deltaD > 1){
        if($deltaD > 365){
            $years = ceil($deltaD/365);
            if($years ==1){
                return "last year"; 
            } else{
                return "<br>$years years ago";
            }   
        }
        if($deltaD > 6){
            return date('d-M',strtotime("$deltaD days ago"));
        }       
        return "$deltaD days ago";
    }
    if($deltaD == 1){
        return "Yesterday";
    }
    if($deltaH == 1){
        return "last hour";
    }
    if($deltaM == 1){
        return "last minute";
    }
    if($deltaH > 0){
        return $deltaH." hours ago";
    }
    if($deltaM > 0){
        return $deltaM." minutes ago";
    }
    else{
        return "few seconds ago";
    }
}
Ramesh
  • 1,829
  • 2
  • 25
  • 30
-1

This function is not made to be used for the English language. I translated the words in English. This needs more fixing before using for English.

function ago($d) {
$ts = time() - strtotime(str_replace("-","/",$d));

        if($ts>315360000) $val = round($ts/31536000,0).' year';
        else if($ts>94608000) $val = round($ts/31536000,0).' years';
        else if($ts>63072000) $val = ' two years';
        else if($ts>31536000) $val = ' a year';

        else if($ts>24192000) $val = round($ts/2419200,0).' month';
        else if($ts>7257600) $val = round($ts/2419200,0).' months';
        else if($ts>4838400) $val = ' two months';
        else if($ts>2419200) $val = ' a month';


        else if($ts>6048000) $val = round($ts/604800,0).' week';
        else if($ts>1814400) $val = round($ts/604800,0).' weeks';
        else if($ts>1209600) $val = ' two weeks';
        else if($ts>604800) $val = ' a week';

        else if($ts>864000) $val = round($ts/86400,0).' day';
        else if($ts>259200) $val = round($ts/86400,0).' days';
        else if($ts>172800) $val = ' two days';
        else if($ts>86400) $val = ' a day';

        else if($ts>36000) $val = round($ts/3600,0).' year';
        else if($ts>10800) $val = round($ts/3600,0).' years';
        else if($ts>7200) $val = ' two years';
        else if($ts>3600) $val = ' a year';

        else if($ts>600) $val = round($ts/60,0).' minute';
        else if($ts>180) $val = round($ts/60,0).' minutes';
        else if($ts>120) $val = ' two minutes';
        else if($ts>60) $val = ' a minute';

        else if($ts>10) $val = round($ts,0).' second';
        else if($ts>2) $val = round($ts,0).' seconds';
        else if($ts>1) $val = ' two seconds';
        else $val = $ts.' a second';


        return $val;
    }
syrkull
  • 2,295
  • 4
  • 35
  • 68
-1

Use of:

echo elapsed_time('2016-05-09 17:00:00'); // 18 saat 8 dakika önce yazıldı.

Function:

function elapsed_time($time){// Nekadar zaman geçmiş

        $diff = time() - strtotime($time); 

        $sec = $diff;
        $min = floor($diff/60);
        $hour = floor($diff/(60*60));
        $hour_min = floor($min - ($hour*60));
        $day = floor($diff/(60*60*24));
        $day_hour = floor($hour - ($day*24));
        $week = floor($diff/(60*60*24*7));
        $mon = floor($diff/(60*60*24*7*4));
        $year = floor($diff/(60*60*24*7*4*12));

        //difference calculate to string
        if($sec < (60*5)){
            return 'şimdi yazıldı.';
        }elseif($min < 60){
            return 'biraz önce yazıldı.';
        }elseif($hour < 24){
            return $hour.' saat '.$hour_min.' dakika önce yazıldı.';
        }elseif($day < 7){
            if($day_hour!=0){$day_hour=$day_hour.' saat ';}else{$day_hour='';}
            return $day.' gün '.$day_hour.'önce yazıldı.';
        }elseif($week < 4){
            return $week.' hafta önce yazıldı.';
        }elseif($mon < 12){
            return $mon.' ay önce yazıldı.';
        }else{
            return $year.' yıl önce yazıldı.';
        }
    }
Limitless isa
  • 3,689
  • 36
  • 28
-1

Slightly modified answer from above:

  $commentTime = strtotime($whatever)
  $today       = strtotime('today');
  $yesterday   = strtotime('yesterday');
  $todaysHours = strtotime('now') - strtotime('today');

private function timeElapsedString(
    $commentTime,
    $todaysHours,
    $today,
    $yesterday
) {
    $tokens = array(
        31536000 => 'year',
        2592000 => 'month',
        604800 => 'week',
        86400 => 'day',
        3600 => 'hour',
        60 => 'minute',
        1 => 'second'
    );
    $time = time() - $commentTime;
    $time = ($time < 1) ? 1 : $time;
    if ($commentTime >= $today || $commentTime < $yesterday) {
        foreach ($tokens as $unit => $text) {
            if ($time < $unit) {
                continue;
            }
            if ($text == 'day') {
                $numberOfUnits = floor(($time - $todaysHours) / $unit) + 1;
            } else {
                $numberOfUnits = floor(($time)/ $unit);
            }
            return $numberOfUnits . ' ' . $text . (($numberOfUnits > 1) ? 's' : '') . ' ago';
        }
    } else {
        return 'Yesterday';
    }
}
Mr Sorbose
  • 777
  • 4
  • 20
  • 34
-2

just pass the date time to this func. it would print out in time ago format for you

date_default_timezone_set('your-time-zone');
function convert($datetime){
  $time=strtotime($datetime);
  $diff=time()-$time;
  $diff/=60;
  $var1=floor($diff);
  $var=$var1<=1 ? 'min' : 'mins';
  if($diff>=60){
    $diff/=60;
    $var1=floor($diff);
    $var=$var1<=1 ? 'hr' : 'hrs';
    if($diff>=24){$diff/=24;$var1=floor($diff);$var=$var1<=1 ? 'day' : 'days';
    if($diff>=30.4375){$diff/=30.4375;$var1=floor($diff);$var=$var1<=1 ? 'month' : 'months';
    if($diff>=12){$diff/=12;$var1=floor($diff);$var=$var1<=1 ? 'year' : 'years';}}}}
    echo $var1,' ',$var,' ago';
  }
hrishi
  • 94
  • 2
  • 4
-2

The following is a very simple and extremely efficient solution.

function timeElapsed($originalTime){

        $timeElapsed=time()-$originalTime;

        /*
          You can change the values of the following 2 variables 
          based on your opinion. For 100% accuracy, you can call
          php's cal_days_in_month() and do some additional coding
          using the values you get for each month. After all the
          coding, your final answer will be approximately equal to
          mine. That is why it is okay to simply use the average
          values below.
        */
        $averageNumbDaysPerMonth=(365.242/12);
        $averageNumbWeeksPerMonth=($averageNumbDaysPerMonth/7);

        $time1=(((($timeElapsed/60)/60)/24)/365.242);
        $time2=floor($time1);//Years
        $time3=($time1-$time2)*(365.242);
        $time4=($time3/$averageNumbDaysPerMonth);
        $time5=floor($time4);//Months
        $time6=($time4-$time5)*$averageNumbWeeksPerMonth;
        $time7=floor($time6);//Weeks
        $time8=($time6-$time7)*7;
        $time9=floor($time8);//Days
        $time10=($time8-$time9)*24;
        $time11=floor($time10);//Hours
        $time12=($time10-$time11)*60;
        $time13=floor($time12);//Minutes
        $time14=($time12-$time13)*60;
        $time15=round($time14);//Seconds

        $timeElapsed=$time2 . 'yrs ' . $time5 . 'months ' . $time7 . 
                     'weeks ' . $time9 .  'days ' . $time11 . 'hrs '
                     . $time13 . 'mins and ' . $time15 . 'secs.';

        return $timeElapsed;

}

echo timeElapsed(1201570814);

Sample output:

6yrs 4months 3weeks 4days 12hrs 40mins and 36secs.

demongolem
  • 9,474
  • 36
  • 90
  • 105
-2

Here's my solution for a notification module I built some time ago. It returns output similar to Facebook's notifications dropdown (eg. 1 day ago, Just now, etc).

public function getTimeDifference($time) {
    //Let's set the current time
    $currentTime = date('Y-m-d H:i:s');
    $toTime = strtotime($currentTime);

    //And the time the notification was set
    $fromTime = strtotime($time);

    //Now calc the difference between the two
    $timeDiff = floor(abs($toTime - $fromTime) / 60);

    //Now we need find out whether or not the time difference needs to be in
    //minutes, hours, or days
    if ($timeDiff < 2) {
        $timeDiff = "Just now";
    } elseif ($timeDiff > 2 && $timeDiff < 60) {
        $timeDiff = floor(abs($timeDiff)) . " minutes ago";
    } elseif ($timeDiff > 60 && $timeDiff < 120) {
        $timeDiff = floor(abs($timeDiff / 60)) . " hour ago";
    } elseif ($timeDiff < 1440) {
        $timeDiff = floor(abs($timeDiff / 60)) . " hours ago";
    } elseif ($timeDiff > 1440 && $timeDiff < 2880) {
        $timeDiff = floor(abs($timeDiff / 1440)) . " day ago";
    } elseif ($timeDiff > 2880) {
        $timeDiff = floor(abs($timeDiff / 1440)) . " days ago";
    }

    return $timeDiff;
}
Ciaran
  • 553
  • 3
  • 11
  • 27
-4

I am using following function for several years. And it is working fine:

function timeDifference($timestamp)
{
    $otherDate=$timestamp;
    $now=@date("Y-m-d H:i:s");

    $secondDifference=@strtotime($now)-@strtotime($otherDate);
    $extra="";
    if ($secondDifference == 2592000) { 
    // months 
    $difference = $secondDifference/2592000; 
    $difference = round($difference,0); 
    if ($difference>1) { $extra="s"; } 
    $difference = $difference." month".$extra." ago"; 
}else if($secondDifference > 2592000)
    {$difference=timestamp($timestamp);} 
elseif ($secondDifference >= 604800) { 
    // weeks 
    $difference = $secondDifference/604800; 
    $difference = round($difference,0); 
    if ($difference>1) { $extra="s"; } 
    $difference = $difference." week".$extra." ago"; 
} 
elseif ($secondDifference >= 86400) { 
    // days 
    $difference = $secondDifference/86400; 
    $difference = round($difference,0); 
    if ($difference>1) { $extra="s"; } 
    $difference = $difference." day".$extra." ago"; 
} 
elseif ($secondDifference >= 3600) { 
    // hours 

    $difference = $secondDifference/3600; 
    $difference = round($difference,0); 
    if ($difference>1) { $extra="s"; } 
    $difference = $difference." hour".$extra." ago"; 
} 
elseif ($secondDifference < 3600) { 
    // hours 
    // for seconds (less than minute)
    if($secondDifference<=60)
    {       
        if($secondDifference==0)
        {
            $secondDifference=1;
        }
        if ($secondDifference>1) { $extra="s"; }
        $difference = $secondDifference." second".$extra." ago"; 

    }
    else
    {

$difference = $secondDifference/60; 
        if ($difference>1) { $extra="s"; }else{$extra="";}
        $difference = round($difference,0); 
        $difference = $difference." minute".$extra." ago"; 
    }
} 

$FinalDifference = $difference; 
return $FinalDifference;
}
Ayyaz Zafar
  • 2,015
  • 5
  • 26
  • 40