I've come across an issue when trying to calculate the amount of days between two dates. If the start date is before a daylight savings switch, the amount of days is calculated incorrectly.
Below is a quick test to reproduce the error:
/**
* @dataProvider daysProvider
*/
public function testDays($start, $end, $expectedDays)
{
$startDate = new \DateTime($start);
$endDate = new \DateTime($end);
$interval = $startDate->diff($endDate);
$this->assertEquals($expectedDays, $interval->format('%a'));
}
/**
* @dataProvider daysProvider
*/
public function testDaysSydney($start, $end, $expectedDays)
{
$startDate = new \DateTime($start);
$endDate = new \DateTime($end);
$startDate->setTimezone(new \DateTimeZone('Australia/Sydney'));
$endDate->setTimezone(new \DateTimeZone('Australia/Sydney'));
$interval = $startDate->diff($endDate);
$this->assertEquals($expectedDays, $interval->format('%a'));
}
public function daysProvider()
{
return [
['2016-03-01', '2016-03-04', 3],
['2016-04-01', '2016-04-04', 3],
];
}
And the output:
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
...F
Time: 23 ms, Memory: 4.00MB
There was 1 failure:
1) TimingTest::testDaysSydney with data set #1 ('2016-04-01', '2016-04-04', 3)
Failed asserting that '2' matches expected 3.
I did find this Bug report: https://bugs.php.net/bug.php?id=63953 but apparently the issue is supposed to be fixed.
Any idea of a workaround for this? Thanks
There is a difference between setting DateTimeZone
via DateTime
setter method (setTimezone
) and setting it via DateTime
constructor (as stated in this question). Try to set timezone via constructor:
public function testDaysSydney($start, $end, $expectedDays)
{
$tz=new \DateTimeZone('Australia/Sydney');
$startDate = new \DateTime($start, $tz);
$endDate = new \DateTime($end, $tz);
$interval = $startDate->diff($endDate);
$this->assertEquals($expectedDays, $interval->format('%a'));
}
make sure you are working with the correct time.
1) One method would be to set the timezone in PHP to either GMT or UTC in php.ini or by using date_default_timezone_set()
. that is what you are trying
2)The other approach would be to using gmdate()
in place of date()
.