Reputation: 69
I need to display the difference in days, hours, minutes and seconds between two dates, in PHP. I've already tried the suggestions offered here:
Create Day, Hour, Minute and Second countdown in PHP
And they all give incorrect results. Here is an example:
$startdate = "2014-03-20 12:34:56";
$enddate = "2014-04-01 13:34:56";
$diff = strtotime($enddate) - strtotime($startdate);
$temp = $diff/86400; // (60 sec/min * 60 min/hr * 24 hr/day = 86400 sec/day)
$dd = floor($temp); $temp = 24*($temp-$dd); //Days
$hh = floor($temp); $temp = 60*($temp-$hh); //Hours
$mm = floor($temp); $temp = 60*($temp-$mm); //Minutes
$ss = floor($temp); //Seconds
echo $dd." days\n".
$hh." hours\n".
$mm." minutes\n".
$ss." seconds";
The results with the two timestamps I've specified should be:
11 days
1 hour
0 minutes
0 seconds
But when I run this, it's giving me:
12 days
0 hours
0 minutes
0 seconds
How can I do this?
Upvotes: 0
Views: 3279
Reputation: 941
$days = 0;
$hours = 0;
$minutes = 0;
$seconds = 0;
$limit_date = new DateTime("2022-06-23 01:11:59");
$time_now = new DateTime("2022-06-22 01:10:00");
$diffInSeconds = $limit_date->getTimestamp() - $time_now->getTimestamp();
if ($diffInSeconds > 0){
if ($diffInSeconds > 60) {
$d = (float)((($diffInSeconds/60)/60)/ 24);
$d_point = $d - floor($d);
$h = (float)($diffInSeconds/60)/60;
$h = (float)($d_point * 24);
$h_point = $h - floor($h);
$m = (float)(($h-floor($h)) * 60);
$m = $h_point * 60;
$m_point = $m - floor($m);
$s = (float)($m_point * 60);
$days = intval($d);
$hours = intval($h);
$hours = intval($h);
$minutes = intval($m);
$seconds = intval($s);
} else {
$seconds = $diffInSeconds;
}
}
echo $days . " " . $hours. ":" . $minutes. ":" . $seconds;
Upvotes: 0
Reputation: 12644
The output you get is correct. The DST in your timezone changes near the end of March. If you consider the output NOT to be correct (you are free to do so), you can do this:
$diff = strtotime($enddate." UTC") - strtotime($startdate." UTC");
and then the rest of your calculation (but: see the EDIT below).
UTC
is the "Coordinated Universal Time", so that the above is a "daylight-savings-less" difference.
If you don't explicitly supply a timezone (like UTC
) to strtotime()
, it will use the default timezone, i.e., the output of date_default_timezone_get()
.
EDIT
It turns out that your algorithm on my machine, with the above modification and with your datetimes, prints the following:
12 days
0 hours
59 minutes
59 seconds
how comes? The reason is that you should never rely on the exactness of floating point arithmetics, in particular of division, except in rare cases. The result of your division is 12.041666666667
, which, a couple of lines later, causes your hours to be 0.99999999999999
instead of 1.0
.
Instead of fixing the algorithm, I suggest to follow the advice by @salathe, and to do this in order to get the result you expect (which may not be the result someone/something else expects):
$diff = date_create($startdate)->diff(date_create($enddate));
echo $diff->format("%a days\n%h hours\n%i minutes\n%s seconds\n");
Otherwise, a fix of your algorithm, that works for both interpretations of the difference, is:
if ($ignore_dst) {
$diff = strtotime($enddate." UTC") - strtotime($startdate." UTC");
} else {
$diff = strtotime($enddate) - strtotime($startdate);
}
$ddss = $diff % 86400;
$dd = ($diff - $ddss) / 86400;
$hhss = $ddss % 3600;
$hh = ($ddss - $hhss) / 3600;
$mmss = $hhss % 60;
$mm = ($hhss - $mmss) / 60;
$ss = $mmss % 60;
Here all variables are integers (you can check with var_dump()
), but even if they were not, division is only done when you already have a multiple of the divisor, which guarantees the result.
Upvotes: 3
Reputation: 3113
Why you dont use the date() function?
date("d", $timestamp); // day
Upvotes: 0