This question already has answers here:
Converting timestamp to time ago in PHP e.g 1 day ago, 2 days ago...
(32 answers)
Closed 9 years ago.
I am trying to display user friendly date formatting such as "1 hour and 15 minutes", "4 days and 8 hours" to the user. However my script is displaying 0 hours as 23 for some reason.
$date = '2014-01-15 15:00' # PAST DATE
$now = Date("Y-m-d H:m:s");
$seconds = strtotime($now) - strtotime($date);
$days = floor($seconds / 86400);
$hours = floor(($seconds - ($days * 86400)) / 3600);
$minutes = floor(($seconds - ($days * 86400) - ($hours * 3600))/60);
$seconds = floor(($seconds - ($days * 86400) - ($hours * 3600) - ($minutes*60)));
if($days > 0)
{
if($days == 1)
{
return $days . ' dag ' . $hours . ' timmar';
} else {
return $days . ' dagar ' . $hours . ' timmar';
}
}
if(($hours < 24) AND ($hours > 0))
{
return $hours . ' timmar';
}
if($minutes < 60)
{
return $minutes . ' minuter';
}
Can anyone see what is causing this? Am I doing it the correct way? Note that $date is user supplied in the past.
There are much easier ways to do this:
$past = new DateTime('2014-01-15 15:00');
$now = new DateTime();
$interval = $now->diff($past);
echo $interval->format('%y years, %m months, %d days,
%h hours, %i minutes, %S seconds');
An obvious improvement is to use now show periods of time that have zero values (i.e. 0 days):
$elapsed = $interval->format('%y years, %m months, %d days,
%h hours, %i minutes');
$elapsed = str_replace(array('0 years,', ' 0 months,', ' 0 days,',
' 0 hours,', ' 0 minutes,'), '', $elapsed);
$elapsed = str_replace(array('1 years, ', ' 1 months, ', ' 1 days, ',
' 1 hours, ', ' 1 minutes'), array('1 year, ',
'1 month, ', ' 1 day, ', ' 1 hour, ', ' 1 minute'),
$elapsed);
Use something like this:
$date = '2014-01-15 15:00' # PAST DATE
now = Date("Y-m-d H:m:s");
$t = strtotime($now) - strtotime($date);
$time = date('g:iA M dS', $t );
$diff = time() - $t;
if ( $diff < 60 )
{
return "a few seconds ago";
}
elseif ( $diff < 3600 )
{
return "about ".( int ) ($diff/60) ." mins ago";
}
elseif ( $diff < 86400 )
{
if ( ( int ) ($diff/3600) == 1 )
{
return "about an hour ago";
}
else
{
return "about ".( int ) ($diff/3600) ." hours ago";
}
}
else if( $diff < 172800 )
{
return "about a day ago";
}
elseif ( $diff > 172800 )
{
return "$time";
}
Related
So, I've got this working code which converts a MySQL date to UNIX Timestamp and subtracts it from the current date() to show a "time elapsed since X"-like timer. (the part which takes the date from database is missing since it's in another script)
<?php
function time_elapsed($secs){
$bit = array(
' year' => $secs / 31556926 % 12,
' week' => $secs / 604800 % 52,
' day' => $secs / 86400 % 7,
' hour' => $secs / 3600 % 24,
' minute' => $secs / 60 % 60,
' second' => $secs % 60
);
foreach($bit as $k => $v){
if($v > 1)$ret[] = $v . $k . 's';
if($v == 1)$ret[] = $v . $k;
}
array_splice($ret, count($ret)-1, 0, 'and');
$ret[] = 'ago.';
return join(' ', $ret);
}
$nowtime = time() + 10; //add 10s to avoid error
$oldtime = strtotime($mysqltime2);
$time_elapsed = time_elapsed($nowtime-$oldtime)."\n";
echo wordwrap($time_elapsed,35,"<br />\n"); //split long line
?>
I managed to fix an error reporting missing array or something if the script was executed at the same time of the MySQL date by adding 10 seconds to the current timestamp.
Another issue I have is that the script shows "and X seconds" even if there aren't minutes/hours/days/etc before it.
E.g.
"and X seconds"
"Y minutes and X seconds"
"Z hours Y minutes and X seconds"
"N days Z hours Y minutes and X seconds"
I want to remove the "and" before seconds ONLY if there's no minutes/hours/etc before it.
Any tip on how to fix this?
You could only splice when needed:
if( count($ret) > 1 ) {
array_splice($ret, count($ret)-1, 0, 'and');
}
Not sure if this will help, but why not do most of the date maths in mysql?
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Here is something I did before to list posts in a comments section of a site, it outputs "post made 2 hours ago" etc
SQL:
UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(made_on) as madeon
PHP (pass madeon from query to here):
function seconds_to_textual_time_ago($seconds)
{
$hour = 60* 60;
$day = 24 * $hour;
$month = 30 * $day;
$year = 365 * $day;
switch(true)
{
case ($seconds < 60) :
$time_ago = "Less than 1 minute ago";
break;
case ($seconds >= 60 && $seconds < $hour):
$minutes = floor($seconds /60);
if ($minutes > 1)
$time_ago = "$minutes minutes ago";
else
$time_ago = "1 minute ago";
break;
case ($seconds >= $hour && $seconds < $day):
$hours = floor($seconds /$hour);
if ($hours > 1)
$time_ago = "$hours hours ago";
else
$time_ago = "1 hour ago";
break;
case ($seconds >= $day && $seconds < $month):
$days = floor($seconds /$day);
if ($days > 1)
$time_ago = "$days days ago";
else
$time_ago = "1 day ago";
break;
case ($seconds >= $month && $seconds < $year):
$months = floor($seconds /$month);
if ($months > 1)
$time_ago = "$months months ago";
else
$time_ago = "1 month ago";
break;
case ($seconds >= $year ):
$years = floor($seconds /$year);
if ($years > 1)
$time_ago = "$years years ago";
else
$time_ago = "1 year ago";
break;
default:
break;
}
return $time_ago;
}
The simplest I can think of is
$time_elapsed = time_elapsed($nowtime-$oldtime))."\n";
if($nowtime-$oldtime < 61){
$time_elapsed=str_replace('and ',' ',$time_elapsed);
}
i have been having trouble displaying the hours and minutes after calculating the difference between 2 different unix timestamps. Lets say i have these 2 unix timestamps:
1) 1384327800
2) 1384300800
the difference is
27000
if i divide 27000/3600 i get
7.5
but what i want is to display
7:30
or
7 hours and 30 minutes
what is the best way to go about this?
All you need to do it a little calculation:
$diff = 27000;
$hour = floor($diff / 3600);
$min = floor(($diff - $hour * 3600) / 60);
$sec = $diff - $hour * 3600 - $min * 60;
echo "$hour hours, $min minutes, $sec seconds";
Or try it with DateTime class:
$dt1 = new DateTime('#1384327800');
$dt2 = new DateTime('#1384300801');
$diff = $dt1->diff($dt2);
echo $diff->format('%h hours, %i minutes, %s seconds');
Algorithmic way (with no automatic calculation with any function/library) :
$diff_in_minutes = ($timestamp1 - $timestamp2) / 60;
$minutes = $diff_in_minutes % 60;
$hours = ($diff_in_minutes - $minutes) / 60;
$diff_string = $hours . ':' . $minutes;
Look at DateTime() and DateInterval::format()
$dt1 = new DateTime('#1384327800');
$dt2 = new DateTime('#1384300800');
$diff = $dt1->diff($dt2);
echo $diff->format('%h hours and %i minutes');
This last little bit will remove unnecessary time periods from your string if so desired.
$elapsed = $diff->format('%y years, %m months, %a days, %h hours, %i minutes, %S seconds');
$elapsed = str_replace(array('0 years,', ' 0 months,', ' 0 days,', ' 0 hours,', ' 0 minutes,'), '', $elapsed);
$elapsed = str_replace(array('1 years, ', ' 1 months, ', ' 1 days, ', ' 1 hours, ', ' 1 minutes'), array('1 year, ', '1 month, ', ' 1 day, ', ' 1 hour, ', ' 1 minute'), $elapsed);
echo $elapsed;
For full long formatting exactly as described:
date_default_timezone_set('UTC');
$timestamp1 = new DateTime('#1384327800');
$timestamp2 = new DateTime('#1384300800');
$diff = $timestamp1->diff($timestamp2);
$timemap = array('y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second');
$timefmt = array();
foreach ($timemap as $prop => $desc) {
if ($diff->$prop > 0) {
$timefmt[] = ($diff->$prop > 1) ? "{$diff->$prop} {$desc}s" : "{$diff->$prop} $desc";
}
}
$diffstr = (count($timefmt) > 1)
? $diff->format(sprintf('%s and %s',
implode(', ', array_slice($timefmt, 0, -1)), end($timefmt)))
: end($timefmt);
var_dump($diffstr);
This gave me the following:
string(22) "7 hours and 30 minutes"
I have in my database 4 columns which are:
Date_in | Time_in | Date_out | Time_out
Date_in and Time_in belong together (e.g., 2013-02-18 13:00:00) and date_out goes with Time_out. I would like to find out the difference between and I have gotten up till:
$start_time = new DateTime("'$list[date_in] "."$list[time_in]'");
$since_start = $start_time->diff(new DateTime("'$list[date_out] "."$list[time_out]'"));
$hours = $since_start->h.' hours';
But it doesn't work. I think my quotes and double quotes are all messed up because the use of " ' . really confuses me..
Thanks in advance for any advice on how I can fix my code!
[EDIT]
Thanks everyone for all your detailed help! I just realised that the server doesn't support php 5.3 and I can't use datetime().
So my solution was:
$start_time = strtotime("$list[date_in] " . "$list[time_in]");
$end_time = strtotime("$list[date_out] " . "$list[time_out]");
$hours = abs(($end_time - $start_time)/3600);
Try this,
function datediff( $date1, $date2 )
{
$diff = abs( strtotime( $date1 ) - strtotime( $date2 ) );
return sprintf
(
"%d Days, %d Hours, %d Mins, %d Seconds",
intval( $diff / 86400 ),
intval( ( $diff % 86400 ) / 3600),
intval( ( $diff / 60 ) % 60 ),
intval( $diff % 60 )
);
}
print datediff( "18th February 2013", "now" ) . "\n";
OR
You can use DateTime::diff
$start_date = new DateTime("2012-02-10 11:26:00");
$end_date = new DateTime("2012-04-25 01:50:00");
$interval = $start_date->diff($end_date);
echo "Result " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days ";
EDIT:
Checkout links,
How to calculate the difference between two dates using PHP?
Php Date Time – 7 Methods to Calculate the Difference between 2 dates.
may help you.
You don't need quotes if you want to evaluate the variables content.
In this case, you only need them to create a separation between date and time:
$start_time = new DateTime($list['date_in']." ".$list['time_in']);
$since_start = $start_time->diff(new DateTime($list['date_out']." ".$list['time_out']));
I am using the dot . in order to concatenate variables with an string, in this case the string is a white space.
You can read more about concatenation in the documentation.
$start_time = new DateTime("$list[date_in] " . "$list[time_in]");
$since_start = $start_time->diff(new DateTime("$list[date_out] " . "$list[time_out]"));
OR
$start_time = new DateTime("{$list['date_in']} {$list['time_in']}");
$since_start = $start_time->diff(new DateTime("{$list['date_out']} {$list['time_out']}"));
// Time format is UNIX timestamp or
// PHP strtotime compatible strings
function dateDiff($time1, $time2, $precision = 6) {
// If not numeric then convert texts to unix timestamps
if (!is_int($time1)) {
$time1 = strtotime($time1);
}
if (!is_int($time2)) {
$time2 = strtotime($time2);
}
// If time1 is bigger than time2
// Then swap time1 and time2
if ($time1 > $time2) {
$ttime = $time1;
$time1 = $time2;
$time2 = $ttime;
}
// Set up intervals and diffs arrays
$intervals = array('year','month','day','hour','minute','second');
$diffs = array();
// Loop thru all intervals
foreach ($intervals as $interval) {
// Set default diff to 0
$diffs[$interval] = 0;
// Create temp time from time1 and interval
$ttime = strtotime("+1 " . $interval, $time1);
// Loop until temp time is smaller than time2
while ($time2 >= $ttime) {
$time1 = $ttime;
$diffs[$interval]++;
// Create new temp time from time1 and interval
$ttime = strtotime("+1 " . $interval, $time1);
}
}
$count = 0;
$times = array();
// Loop thru all diffs
foreach ($diffs as $interval => $value) {
// Break if we have needed precission
if ($count >= $precision) {
break;
}
// Add value and interval
// if value is bigger than 0
if ($value > 0) {
// Add s if value is not 1
if ($value != 1) {
$interval .= "s";
}
// Add value and interval to times array
$times[] = $value . " " . $interval;
$count++;
}
}
// Return string with times
return implode(", ", $times);
}
// Set start & end time
$start_time = "2013-02-18 13:00:00";
$end_time = "2013-02-16 10:00:00";
// Run and print diff
echo dateDiff($start_time, $end_time, 6);
The last argument is the precision.
$diff = abs( strtotime( '2014-04-25 16:00:00' ) - strtotime( '2014-04-27 18:02:00' ) );
if(sprintf("%d",intval( $diff / 86400 )) != '0'){
if(sprintf("%d",intval( $diff / 86400 )) == '1'){
echo sprintf("%02d day ", intval( $diff / 86400 ));
}else{
echo sprintf("%02d days ", intval( $diff / 86400 ));
}
}
if(intval( ( $diff % 86400 ) / 3600) != '0'){
if(intval( ( $diff % 86400 ) / 3600) == '1'){
echo sprintf("%02d hour ", intval( ( $diff % 86400 ) / 3600));
}else{
echo sprintf("%02d hours ", intval( ( $diff % 86400 ) / 3600));
}
}
if(intval( ( $diff / 60 ) % 60 ) != '0'){
if(intval( ( $diff / 60 ) % 60 ) == '1'){
echo sprintf("%02d min", intval( ( $diff / 60 ) % 60 ));
}else{
echo sprintf("%02d mins", intval( ( $diff / 60 ) % 60 ));
}
}
For example if I have:
$seconds = 3744000; // i want to output: 43 days, 8 hours, 0 minutes
Do I have to create a function to convert this? Or does PHP already have something built in to do this like date()?
function secondsToWords($seconds)
{
$ret = "";
/*** get the days ***/
$days = intval(intval($seconds) / (3600*24));
if($days> 0)
{
$ret .= "$days days ";
}
/*** get the hours ***/
$hours = (intval($seconds) / 3600) % 24;
if($hours > 0)
{
$ret .= "$hours hours ";
}
/*** get the minutes ***/
$minutes = (intval($seconds) / 60) % 60;
if($minutes > 0)
{
$ret .= "$minutes minutes ";
}
/*** get the seconds ***/
$seconds = intval($seconds) % 60;
if ($seconds > 0) {
$ret .= "$seconds seconds";
}
return $ret;
}
print secondsToWords(3744000);
This is very simple and easy to find days , hours, minute and second in core php :
$dbDate = strtotime("".$yourdbtime."");
$endDate = time();
$diff = $endDate - $dbDate;
$days = floor($diff/86400);
$hours = floor(($diff-$days*86400)/(60 * 60));
$min = floor(($diff-($days*86400+$hours*3600))/60);
$second = $diff - ($days*86400+$hours*3600+$min*60);
if($days > 0) echo $days." Days ago";
elseif($hours > 0) echo $hours." Hours ago";
elseif($min > 0) echo $min." Minutes ago";
else echo "Just now";
An easy way to accomplish this nowadays is using DateTimeImmutable, DateInterval and PHP 5.5.0 or higher:
$seconds = 3744000;
$interval = new DateInterval("PT{$seconds}S");
$now = new DateTimeImmutable('now', new DateTimeZone('utc'));
$difference = $now->diff($now->add($interval))->format('%a days, %h hours, %i minutes');
The result will be:
43 days, 8 hours, 0 minutes
The code adds the seconds to a date and calculates the difference to it. Like this, the seconds are transformed into the specified days, hours and minutes.
Warning 1: Working without UTC - Clock changes
You may not specify the DateTimeZone in the constructor of the DateTimeImmutable object to UTC.
$now = new DateTimeImmutable();
There are regions in this world, where the clock changes on specific days of the year. Most countries in the EU change between a summer- and winter-time for example.
If your date interval overlaps the day on that a clock change occurs and your server is set to the related region for that clock change, the result might change as well. This is best shown with the following example:
$twentyFourHours = new DateInterval('PT24H');
$twentyFiveHours = new DateInterval('PT25H');
//Pacific time changed from summer- to winter-time on that day
$summerToWinter = new DateTimeImmutable('2018-11-04');
If you add 24 hours to the $summerToWinter date, you will get the following result:
$extra24Hours = $summerToWinter->add($twentyFourHours);
echo $summerToWinter->format('y-m-d H:i');
echo $extra24Hours->format('y-m-d H:i');
echo $summerToWinter->diff($extra24Hours)->format('%a days, %h hours, %i minutes');
18-11-04 00:00
18-11-04 23:00
0 days, 24 hours, 0 minutes
As you can see, between 00:00 and 23:00 on that day lay 24 hours, which is technically correct. Because of the clock change the timelap between 02:00 and 03:00 occured twice on that day.
Adding 25 hours will result in this:
$extra25Hours = $summerToWinter->add($twentyFiveHours);
echo $summerToWinter->format('y-m-d H:i');
echo $extra25Hours->format('y-m-d H:i');
echo $summerToWinter->diff($extra25Hours)->format('%a days, %h hours, %i minutes');
18-11-04 00:00
18-11-05 00:00
1 days, 0 hours, 0 minutes
As we can see, 1 day elapsed, that has had 25 hours. If this is applied for the 3744000 seconds from the original question, the result would show:
43 days, 7 hours, 0 minutes
The information, that an elapsed day has had 25 hours, is not shown though.
Also, I was not able to recreate the same effect for a day that changes the clock from winter to summer time, that should only elapse 23 hours.
Warning 2: Working with the raw DateInterval object
Using this code without DateTimeImmutable will cause the wrong output:
$seconds = 3744000;
$interval = new DateInterval("PT{$seconds}S");
$difference = $interval->format('%a days, %h hours, %i minutes, %s seconds');
Now, only the seconds are set in the DateInterval object. $difference would be:
(unknown) days, 0 hours, 0 minutes, 3744000 seconds
I like Ian Gregory's answer the most and upvoted it but thought i'd just simplify it a little bit :
function secondsToWords($seconds)
{
$days = intval(intval($seconds) / (3600*24));
$hours = (intval($seconds) / 3600) % 24;
$minutes = (intval($seconds) / 60) % 60;
$seconds = intval($seconds) % 60;
$days = $days ? $days . ' days' : '';
$hours = $hours ? $hours . ' hours' : '';
$minutes = $minutes ? $minutes . ' minutes' : '';
$seconds = $seconds ? $seconds . ' seconds' : '';
return $days . $hours . $minutes . $seconds;
}
Is there a PHP library that will convert a unix timestamp into something like this format:
8 hours and 17 minutes ago
I made my own script a while back that did this, I just can't track it down and would rather not spend the time recreating it (plus I think it could have been done far more efficiently).
My original code was something along the lines of:
$seconds = time() - $timestamp;
$minutes = 0;
$hours = 0;
$days = 0;
$weeks = 0;
$months = 0;
$years = 0;
while($seconds >= 60)
{
$seconds -= 60;
$minutes ++;
if($minutes >= 60)
{
$minutes -= 60;
$hours ++;
if($hours >= 24)
{
// etc
}
}
}
if($hours < 1) return "$minutes minute" . ($minutes == 1 ? "" : "s")) . " and $seconds seconds" . ($seconds == 1 ? "" : "s"));
if($minutes < 1) return "$seconds second" . ($seconds == 1 ? "" : "s"));
// etc
Better yet, if there's a nicer way to approach the above I'll give it a crack myself as well.
Yes, check The DateTime class.
$datetime1= new DateTime();
$datetime2= new DateTime();
$datetime2->setTimestamp($timestamp);
$interval = $datetime2->diff($datetime1);
echo $interval->format('%a days %h hours and %i minutes ago');
function TimeAgo($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(); }
// Calculate the difference in seconds betweeen
// the two timestamps
$difference = $dateto - $datefrom;
// If difference is less than 60 seconds,
// seconds is a good interval of choice
if($difference < 60)
{
$interval = "s";
}
// If difference is between 60 seconds and
// 60 minutes, minutes is a good interval
elseif($difference >= 60 && $difference<60*60)
{
$interval = "n";
}
// If difference is between 1 hour and 24 hours
// hours is a good interval
elseif($difference >= 60*60 && $difference<60*60*24)
{
$interval = "h";
}
// If difference is between 1 day and 7 days
// days is a good interval
elseif($difference >= 60*60*24 && $difference<60*60*24*7)
{
$interval = "d";
}
// If difference is between 1 week and 30 days
// weeks is a good interval
elseif($difference >= 60*60*24*7 && $difference <
60*60*24*30)
{
$interval = "ww";
}
// 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
elseif($difference >= 60*60*24*30 && $difference <
60*60*24*365)
{
$interval = "m";
}
// 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
elseif($difference >= 60*60*24*365)
{
$interval = "y";
}
// 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($interval)
{
case "m":
$months_difference = floor($difference / 60 / 60 / 24 /
29);
while (mktime(date("H", $datefrom), date("i", $datefrom),
date("s", $datefrom), date("n", $datefrom)+($months_difference),
date("j", $dateto), date("Y", $datefrom)) < $dateto)
{
$months_difference++;
}
$datediff = $months_difference;
// We need this in here because it is possible
// to have an 'm' interval and a months
// difference of 12 because we are using 29 days
// in a month
if($datediff==12)
{
$datediff--;
}
$res = ($datediff==1) ? "$datediff month ago" : "$datediff
months ago";
break;
case "y":
$datediff = floor($difference / 60 / 60 / 24 / 365);
$res = ($datediff==1) ? "$datediff year ago" : "$datediff
years ago";
break;
case "d":
$datediff = floor($difference / 60 / 60 / 24);
$res = ($datediff==1) ? "$datediff day ago" : "$datediff
days ago";
break;
case "ww":
$datediff = floor($difference / 60 / 60 / 24 / 7);
$res = ($datediff==1) ? "$datediff week ago" : "$datediff
weeks ago";
break;
case "h":
$datediff = floor($difference / 60 / 60);
$res = ($datediff==1) ? "$datediff hour ago" : "$datediff
hours ago";
break;
case "n":
$datediff = floor($difference / 60);
$res = ($datediff==1) ? "$datediff minute ago" :
"$datediff minutes ago";
break;
case "s":
$datediff = $difference;
$res = ($datediff==1) ? "$datediff second ago" :
"$datediff seconds ago";
break;
}
return $res;
}
/*
Input parameter is the UNIX timestamp
of the starting date.
The second parameter is optional -
It's value is the ending date,
also UNIX timestamp. If this
parameter is not given, the
default date is current date.
*/
function duration($start,$end=null) {
$end = is_null($end) ? time() : $end;
$seconds = $end - $start;
$days = floor($seconds/60/60/24);
$hours = $seconds/60/60%24;
$mins = $seconds/60%60;
$secs = $seconds%60;
$duration='';
if($days>0) $duration .= "$days days ";
if($hours>0) $duration .= "$hours hours ";
if($mins>0) $duration .= "$mins minutes ";
if($secs>0) $duration .= "$secs seconds ";
//$duration = trim($duration);
if($duration=='') $duration = '0 seconds';
return $duration;
}
It it not suits you better use some classes, given below
http://www.phpclasses.org/browse/file/6330.html