2

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/>';
} 
John Conde
  • 217,595
  • 99
  • 455
  • 496
MEAT
  • 49
  • 6
  • 2
    I don't know what the expected result is, but I would recommend using DateTime class to find time differences. – kennypu Sep 10 '14 at 00:25
  • 2
    ^ [`DateTime::diff()`](http://php.net/manual/en/datetime.diff.php) – Sam Sep 10 '14 at 00:25

3 Answers3

5

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

John Conde
  • 217,595
  • 99
  • 455
  • 496
1

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/>';
}
Kevin
  • 41,694
  • 12
  • 53
  • 70
1
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;
}
sectus
  • 15,605
  • 5
  • 55
  • 97