Chris F
Chris F

Reputation: 69

Need to show days, hours, minutes and seconds between two dates in PHP

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

Answers (4)

Mahmoud Magdy
Mahmoud Magdy

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;

enter image description here

Upvotes: 0

Walter Tross
Walter Tross

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

fejese
fejese

Reputation: 4628

Daylight saving changed between

Upvotes: 2

Adrian Preuss
Adrian Preuss

Reputation: 3113

Why you dont use the date() function?

 date("d", $timestamp); // day

Upvotes: 0

Related Questions