104

2009-10-05 18:11:08

2009-10-05 18:07:13

This should generate 235,how to do it ?

Misier
  • 1,455
  • 4
  • 13
  • 15
  • 1
    Possible duplicate of [Calculate total seconds in PHP DateInterval](http://stackoverflow.com/questions/3176609/calculate-total-seconds-in-php-dateinterval) – FactoryAidan Feb 18 '16 at 00:55

10 Answers10

185

With DateTime objects, you can do it like this:

$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );

$diffInSeconds = $date2->getTimestamp() - $date->getTimestamp();
jonathancardoso
  • 11,737
  • 7
  • 53
  • 72
  • 1
    This also takes daylight savings time into account! – Brainware May 05 '17 at 03:25
  • 5
    This is the most elegant solution to the question. This should be the accepted answer. – Giel Berkers Jan 04 '18 at 08:43
  • 1
    Note that, in order for daylight savings to be taken into account correctly, you need to provide the correct DateTimeZone. If your system is set up correctly then php might already know your timezone from the system default. If in question, manually instanciate one like so: $tz = new DateTimeZone('Europe/Berlin'); and pass it to the DateTime constructor as second parameter. – j4k3 Jan 04 '19 at 14:30
  • great solution but for longer periods (example 1 hour) I receive negative value (overflow?), any idea how to fix this? – marto Jun 02 '19 at 20:20
172

You can use strtotime() to do that:

$diff = strtotime('2009-10-05 18:11:08') - strtotime('2009-10-05 18:07:13')

A similar approach is possible with DateTime objects, e.g.

$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );

$diff = $date2->getTimestamp() - $date->getTimestamp();
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
  • 1
    Note: Be sure you use capital "H" for hours (24h mode) when your "lower" time is "now" and you use `date()` to get datetime of now ( `date("Y-m-d H:i:s")` ). – jave.web Nov 15 '15 at 19:38
  • 1
    ``` Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed. If, however, the year is given in a two digit format and the separator is a dash (-, the date string is parsed as y-m-d. To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates or DateTime::createFromFormat() when possible. ``` – Nikola Petkanski Jun 26 '18 at 10:43
  • check JCM answer and choose your case – Leandro Bardelli Aug 21 '18 at 00:00
10

PHP Date Time reference is helpful for things like this: PHP Date Time Functions

strtotime() is probably the best way.

$seconds = strtotime('2009-10-05 18:11:08') - strtotime('2009-10-05 18:07:13')
Andrew
  • 9,967
  • 10
  • 64
  • 103
9

For those worrying about the limitations of using timestamps (i.e. using dates before 1970 and beyond 2038), you can simply calculate the difference in seconds like so:

$start = new DateTime('2009-10-05 18:07:13');
$end = new DateTime('2009-10-05 18:11:08');
$diff = $start->diff($end);

$daysInSecs = $diff->format('%r%a') * 24 * 60 * 60;
$hoursInSecs = $diff->h * 60 * 60;
$minsInSecs = $diff->i * 60;

$seconds = $daysInSecs + $hoursInSecs + $minsInSecs + $diff->s;

echo $seconds; // output: 235

Wrote a blog post for those interested in reading more.

DrBeco
  • 11,237
  • 9
  • 59
  • 76
designcise
  • 4,204
  • 1
  • 17
  • 13
6

Because of unix epoch limitations, you could have problems compairing dates before 1970 and after 2038. I choose to loose precision (=don't look at the single second) but avoid to pass trough unix epoch conversions (getTimestamp). It depends on what you are doing to do...

In my case, using 365 instead (12*30) and "30" as mean month lenght, reduced the error in an usable output.

function DateIntervalToSec($start,$end){ // as datetime object returns difference in seconds
    $diff = $end->diff($start);
    $diff_sec = $diff->format('%r').( // prepend the sign - if negative, change it to R if you want the +, too
                ($diff->s)+ // seconds (no errors)
                (60*($diff->i))+ // minutes (no errors)
                (60*60*($diff->h))+ // hours (no errors)
                (24*60*60*($diff->d))+ // days (no errors)
                (30*24*60*60*($diff->m))+ // months (???)
                (365*24*60*60*($diff->y)) // years (???)
                );
    return $diff_sec;
}

Note that the error could be 0, if "mean" quantities are intended for diff. The PHP docs don't speaks about this... In a bad case, error could be:

  • 0 seconds if diff is applied to time gaps < 1 month
  • 0 to 3 days if diff is applied to time gaps > 1 month
  • 0 to 14 days if diff is applied to time gaps > 1 year

I prefer to suppose that somebody decided to consider "m" as 30 days and "y" as 365, charging "d" with the difference when "diff" walk trough non-30-days months...

If somebody knows something more about this and can provide official documentation, is welcome!

MilkThief
  • 69
  • 1
  • 3
  • Use the days property instead of the d property to get the exact days in between the two days. So no inaccurate results there. – Nilz11 Nov 27 '16 at 15:16
3
strtotime("2009-10-05 18:11:08") - strtotime("2009-10-05 18:07:13")
Dominic Rodger
  • 97,747
  • 36
  • 197
  • 212
jcoder
  • 29,554
  • 19
  • 87
  • 130
0

The solution proposed by @designcise is wrong when "end date" is before "start date". Here is the corrected calculation

$diff = $start->diff($end);

$daysInSecs = $diff->format('%r%a') * 24 * 60 * 60;
$hoursInSecs = $diff->format('%r%h') * 60 * 60;
$minsInSecs = $diff->format('%r%i') * 60;

$seconds = $daysInSecs + $hoursInSecs + $minsInSecs + $diff->format('%r%s');
0

I know this is an old question, but I had a similar problem and came up with this solution that should work for almost any date, including those before 1970 or after 2038:

$loDate = new DateTime('1000-01-01');
$hiDate = new DateTime('2525-01-01');

if ($hiDate >= $loDate) {
    $diff = $loDate->diff($hiDate);
    $seconds = bcmul((string) $diff->days, '86400');

    if ($diff->h > 0 || $diff->i > 0 || $diff->s > 0) {
        $seconds = bcadd($seconds, (string) ($diff->h * 3600));
        $seconds = bcadd($seconds, (string) ($diff->i * 60));
        $seconds = bcadd($seconds, (string) $diff->s);
    }
 }

The DateTime class is not smart enough to account for calendar changes made in 1752 (when Sept 2, 1752 was followed by Sept 14, 1752), so don't count on this to handle historical dates correctly.

lfjeff
  • 1,840
  • 2
  • 17
  • 19
0
$date1 = new DateTime('2009-10-05 18:11:08');
$date2 = new DateTime('2009-10-05 18:07:13');
$interval = $date1->diff($date2);
echo $interval->s + $interval->i * 60 + $interval->h * 3600 + $interval->days * 86400;
Naseem
  • 24
  • 5
  • Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P Apr 03 '23 at 19:41
-1

A simple and exact solution (exemplifying Nilz11's comment):

$hiDate = new DateTime("2310-05-22 08:33:26");
$loDate = new DateTime("1910-11-03 13:00:01");
$diff = $hiDate->diff($loDate);
$secs = ((($diff->format("%a") * 24) + $diff->format("%H")) * 60 + 
   $diff->format("%i")) * 60 + $diff->format("%s");
Arfon
  • 69
  • 5