112

What is the best way to calculate the total number of seconds between two dates? So far, I've tried something along the lines of:

$delta   = $date->diff(new DateTime('now'));
$seconds = $delta->days * 60 * 60 * 24;

However, the days property of the DateInterval object seems to be broken in the current PHP5.3 build (at least on Windows, it always returns the same 6015 value). I also attempted to do it in a way which would fail to preserve number of days in each month (rounds to 30), leap years, etc:

$seconds = ($delta->s)
         + ($delta->i * 60)
         + ($delta->h * 60 * 60)
         + ($delta->d * 60 * 60 * 24)
         + ($delta->m * 60 * 60 * 24 * 30)
         + ($delta->y * 60 * 60 * 24 * 365);

But I'm really not happy with using this half-assed solution.

efritz
  • 5,047
  • 4
  • 22
  • 33
  • What is the result of `$delta->format("%r%s")` ? – warrenm Jul 05 '10 at 00:01
  • 1
    @warrenm The problem with `format` is when say the number of seconds is 0 while the number of minutes is 1, `$delta->format("%r%s")` turns out to be 0 :( – Vadim Samokhin Aug 15 '12 at 14:34
  • 5
    Worse yet, speaking as somebody now fixing a defect caught in code review from a coder who pasted your EXACT code above -- not every month has 30 days, and not every year has 365 days. :) [Edit: and that coder may have been myself!] – taiganaut Nov 02 '12 at 21:42

7 Answers7

234

Could you not compare the time stamps instead?

$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()
Ben
  • 19,879
  • 11
  • 69
  • 113
  • 13
    I guess I didn't RTFM... This is what I was looking for; thanks a lot! – efritz Jul 05 '10 at 01:24
  • 3
    +1: nice and clean! Note that `getTimestamp()` method is available in PHP >= 5.3.0. – Sk8erPeter Jun 19 '12 at 11:43
  • 1
    I think this works without lurking edge cases (wouldn't bet my life on it though having just spent 10 months doing a DateTime refactor of a large PHP app) but it should be noted that it's a workaround that doesn't solve the comparing-DateIntervals problem. It'd still be really nice to have that ability. – taiganaut Nov 02 '12 at 21:41
  • 7
    If you're stuck with PHP 5.2 on your crappy shared hoster, use `format('U')` instead of `getTimestamp()`. – chiborg Nov 26 '12 at 14:51
  • @chiborg. Nice suggestion. Or change host, no-one ought to be stuck with a crappy host :) – Ben Nov 26 '12 at 22:23
  • 4
    Your solution is not compatible w/ year 2038 bug – Jack M. Jun 27 '14 at 09:02
  • 11
    @JackM. Good to know. I do hope whatever is being built now isn't running anymore in 2037. Feel free to provide a year 2038 bug safe alternative solution. – Ben Jun 27 '14 at 09:59
  • 2
    This is not the answer to this question, why is it accepted. – Danon Jun 12 '17 at 07:20
  • @Danon We'll wait until you provide a better answer then – Ben Jun 14 '17 at 13:07
  • 1
    @Ben the question was seconds between 2 dates, not 1 date and current time. – Danon Jun 16 '17 at 08:57
  • 4
    @Danon well.. 1) current time (now) is a date, as a DateTime object (and shouldn't stretch one's imagination to change it to another DateTime). 2) the OP's question explicitly use current time as a reference example to address. 3) a majority of people seems to agree – Ben Jun 17 '17 at 12:14
  • @JackM. Is it compatible with year 2038 on 64-bit systems? If so, will 32-bit PHP remain supported in 2038? – Damian Yerrick Feb 19 '18 at 17:35
39

This function allows you to get the total duration in seconds from a DateInterval object

/**
 * @param DateInterval $dateInterval
 * @return int seconds
 */
function dateIntervalToSeconds($dateInterval)
{
    $reference = new DateTimeImmutable;
    $endTime = $reference->add($dateInterval);

    return $endTime->getTimestamp() - $reference->getTimestamp();
}
dave1010
  • 14,728
  • 6
  • 66
  • 64
  • 2
    It should be noted that DateTimeImmutable is only available from PHP 5.5 or higher. – XtraBytesLab May 07 '15 at 11:34
  • I think you have to replace the return variables `$endTime` and `$reference` with each other, since this gives me a minus result with a future interval datetime value. – AlexioVay Jun 01 '18 at 13:42
  • 1
    I don't think Timestamp is in Seconds either. PHP DateTime = Horrific API – Quadrivium Nov 30 '18 at 00:29
4

You could do it like this:

$currentTime = time();
$timeInPast = strtotime("2009-01-01 00:00:00");

$differenceInSeconds = $currentTime - $timeInPast;

time() returns the current time in seconds since the epoch time (1970-01-01T00:00:00), and strtotime does the same, but based on a specific date/time you give.

xil3
  • 16,062
  • 8
  • 58
  • 95
4
static function getIntervalUnits($interval, $unit)
{
    // Day
    $total = $interval->format('%a');
    if ($unit == TimeZoneCalc::Days)
        return $total;
    //hour
    $total = ($total * 24) + ($interval->h );
    if ($unit == TimeZoneCalc::Hours)
        return $total;
    //min
    $total = ($total * 60) + ($interval->i );
    if ($unit == TimeZoneCalc::Minutes)
        return $total;  
    //sec
    $total = ($total * 60) + ($interval->s );
    if ($unit == TimeZoneCalc::Seconds)
        return $total;  

    return false;
}
Shoe
  • 72,892
  • 33
  • 161
  • 264
hoofuz
  • 49
  • 2
3

DateTime::diff returns a DateInterval object between 2 dates.

The DateInterval object gives all the informations (the number of days, hours, minutes, seconds).

Here's a sample code:

/**
 * intervalToSeconds
 *
 * @param  DateInterval $interval
 * @return int
 */
function intervalToSeconds(\DateInterval $interval) {
    return $interval->days * 86400 + $interval->h * 3600 + $interval->i * 60 + $interval->s;
}

$date_1 = new \DateTime('2021-03-03 05:59:19');
$date_2 = new \DateTime('now');
$interval = $date_1->diff($date_2);
echo intervalToSeconds($interval);
migli
  • 2,043
  • 20
  • 28
-6

It always feels nice when what you need is already present as a class. In your case, you need a total number of seconds. Why not make a class out of that? The code could look like that:

(new TotalFullSeconds(
    new IntervalFromRange(
        new DateTimeFromISO8601String('2017-07-03T14:27:39+00:00'),
        new DateTimeFromISO8601String('2017-07-05T14:27:39+00:00')
    )
))
    ->value()

Besides being intuitive, you can also benefit from autocompletion facility of your IDE.

For more useful implementation, you can check out this library.

Vadim Samokhin
  • 3,274
  • 4
  • 39
  • 66
-9

You could just put in the hard numbers (instead of 60*60 - put in 3600) so it doesn't need to calculate them each time.

Edit - fixed the number based off your comment.

Duniyadnd
  • 3,902
  • 1
  • 21
  • 25
  • That'd be fine, and it would probably run a fraction of a second faster in PHP, but it still leaves me with the same mis-calculation as the example above. – efritz Jul 05 '10 at 01:26