117

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,125
  • 4
  • 24
  • 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

5 Answers5

248

Could you not compare the time stamps instead?

$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()
Ben
  • 20,737
  • 12
  • 71
  • 115
  • 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
  • 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
  • @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
47

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
  • 15,135
  • 7
  • 67
  • 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
7

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,692
  • 27
  • 32
6

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,305
  • 8
  • 63
  • 97
5
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
  • 74,840
  • 36
  • 166
  • 272
hoofuz
  • 59
  • 1
  • 2