PHP DateInterval on DST change

Most areas in North America and Europe, and some areas in the Middle East observe daylight saving time (DST). So how does DateInterval manage DST changes? Let’s see this by running some code.

In Belgium, we adjust the clock backwards on the last Sunday of October. In 2016, that will be the 30th of October.

echo date_default_timezone_get(); // prints "Europe/Brussels"
$dt1 = new DateTime('2016-10-29 10:00:00');
$dt2 = new DateTime('2016-10-31 09:00:00');

var_dump( $dt1->diff($dt2) );

Output :

DateInterval Object
(
    [y] => 0
    [m] => 0
    [d] => 2
    [h] => -1
    [i] => 0
    [s] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 1
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)

Let’s compare it with a period that doesn’t include a DST change:

$dt1 = new DateTime('2016-10-25 10:00:00');
$dt2 = new DateTime('2016-10-27 09:00:00');

var_dump( $dt1->diff($dt2) );

Output:

DateInterval Object
(
    [y] => 0
    [m] => 0
    [d] => 1
    [h] => 23
    [i] => 0
    [s] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 1
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)

According to the results of the code above, we can see that the date interval between two dates where DST occurs will be 2 days – 1 hours instead of 1 day + 23 hours.
Let’s try to figure out why:

$dateTime = new DateTime('2016-10-29 10:00:00');
$dateTime->add(new DateInterval('P1D'));
$dateTime->add(new DateInterval('PT23H'));

var_dump($dateTime); // 2016-10-31 09:00:00

$dateTime = new DateTime('2016-10-29 10:00:00');
$dateTime->add(new DateInterval('PT23H'));
$dateTime->add(new DateInterval('P1D'));

var_dump($dateTime); // 2016-10-31 08:00:00

We notice above that adding 23 hours and then adding 1 day gives a different result than adding 1 day and then adding 23 hours.
Note that HHVM prints 2016-10-31 09:00:00 for both dates.

$dateTime = new DateTime('2016-10-29 10:00:00');
$dateTime->add(new DateInterval('P2D'));
$dateTime->sub(new DateInterval('PT1H'));

var_dump($dateTime); // 2016-10-31 09:00:00

$dateTime = new DateTime('2016-10-29 10:00:00');
$dateTime->sub(new DateInterval('PT1H'));
$dateTime->add(new DateInterval('P2D'));

var_dump($dateTime); // 2016-10-31 09:00:00

However, adding 2 days and subtracting 1 hour, or firstly subtracting 1 hour and then adding 2 days will be consistent and give the same result.

Post a Comment