MEAT
MEAT

Reputation: 49

PHP strtotime Issue with date differences

Anyone can explain me what is wrong with strtotime function in this example? I'm trying to count differences between dates. PHP 5.6.0 (cli) (built: Aug 28 2014 08:03:51) When i execute this loop it displays number 88 twice.

date_default_timezone_set('Europe/London');
for($i=1;$i<=100;$i++){
    $daysAfterTime = floor( abs( strtotime('2014-01-01') - strtotime('2014-01-01 +'.$i.' days')  )/(60*60*24));
    echo $daysAfterTime.'<br/>';
} 

Upvotes: 2

Views: 297

Answers (3)

John Conde
John Conde

Reputation: 219824

strtotime() is not intended for date math. The manual even says so.

Using this function for mathematical operations is not advisable.

Days are not exactly 60*60*24 seconds long, etc.

As mentioned in the comments DateTime() is much better suited for this as it accounts for things like daylight savings time, leap year, etc. Here's an advanced way of performing the same operation using DateTime(), DateInterval(), and DatePeriod() that is also clearer to anyone trying to figure out what's going on.

$start    = new DateTimeImmutable('2014-01-01', new DateTimeZone('Europe/London'));
$finish   = $start->modify('+101 days'); // extra day as the last day is not inclusive
$interval = new DateInterval('P1D');     // interval of one day 
$period   = new DatePeriod($start, $interval, $finish);
foreach ($period as $date) {
    $diff = $start->diff($date);
    echo $diff->days . "<br>";
} 

Demo

Upvotes: 5

sectus
sectus

Reputation: 15464

date_default_timezone_set('Europe/London');
echo (strtotime('2014-01-01 +89 days') - strtotime('2014-01-01 +88 days'))/(60*60), ' hours per day';
// 23 hours per day

I think that Europe/London timezone uses DST

Info about DST of London: http://www.timeanddate.com/time/zone/uk/london

var_dump(date('Y-m-d',strtotime('2014-01-01 +88 days')));
// string(10) "2014-03-30"

P.S. Using date with z works as expected.

date_default_timezone_set('Europe/London');
for($i=1;$i<=100;$i++){
    $daysAfterTime = date('z', strtotime('2014-01-01 +'.$i.' days')) - date('z', strtotime('2014-01-01'));
    echo $daysAfterTime.PHP_EOL;
}

Upvotes: 1

Kevin
Kevin

Reputation: 41885

I don't know whats the expected output but the other 88 result is because of that floor() function. It rounded the lowest value thus the 88 repeated. Switch the growing value minus the constant value instead so that you don't need to use abs() and use ceil().

date_default_timezone_set('Europe/London');
for($i=1;$i<=100;$i++){
    $daysAfterTime = ceil((strtotime('2014-01-01 +'.$i.' days') - strtotime('2014-01-01'))/(60*60*24));
    echo $daysAfterTime.'<br/>';
}

Upvotes: 1

Related Questions