Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
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?
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';
}
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';
}
}
}
30days for month
, and 12x30days for year
, and because of that it will return invalid number of years bellow year <= 1978. Example where it returns 39 years, but it should 38. And it also doesn't work for years bellow 1970.
$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";
}
}
}
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.
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
2020-12-19 13:12:58
with this plugin
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',
);
explode
and array_combine
.
global
? Read some www.PhpTheRightWay.com please.
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) );
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;
}
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;
}
?>
switch (true)
even though $time
will evaluate to true
?
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;
}
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";
}
}
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);
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
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
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';
}
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.
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);
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.
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?
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;
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();
}
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 :)
$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;
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
# 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";
}
}
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;
}
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ı.';
}
}
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';
}
}
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.
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;
}
Success story sharing
$full
should be a string input to filter the output as needed). e.g.time_elapsed_string($datetime, $format = "ymw")
. P.S. Flat version: stackoverflow.com/a/5010169/318765$full = false
to$level = 7
andif (!$full) $string = array_slice($string, 0, 1);
to$string = array_slice($string, 0, $level);
and calltime_elapsed_string($datetime, 2)
to obtain only the two highest date strings. I think this shoud fit all needs.Unknown property (w)
at this line$diff->w = floor($diff->d / 7);
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: stackoverflow.com/a/32723846/235633