Xenology
Xenology

Reputation: 2452

PHP DateTime does not correctly calculate time component when adding across DST boundaries

Consider the following code

$participantTriggerDate = new \DateTime('2019-06-14 09:40:00.000000', new DateTimeZone('US/Central'));
$dateInterval = new \DateInterval('P150D');

$newDate = \DateTimeImmutable::createFromMutable($participantTriggerDate);
$newDate = $newDate->add($dateInterval);

echo(json_encode([
    'participantTriggerDate' => $participantTriggerDate,
    'newDate' => $newDate,
]));

This code produces the following output:

{
  "participantTriggerDate": {
    "date": "2019-06-14 09:40:00.000000",
    "timezone_type": 3,
    "timezone": "US/Central"
  },
  "newDate": {
    "date": "2019-11-11 09:40:00.000000",
    "timezone_type": 3,
    "timezone": "US/Central"
  }
}

However because 150 days past 2019-06-14 crosses a DST boundary, shouldn't PHP subtract and hour from the time? I thought that PHP took care of all the messy DST stuff under the hood. Is there a way for me to correctly calculate this time? From what I've read it looks like the recommended answer is to convert everything to UTC and do the calculations there. I would like to avoid this if possible. I figured PHP would be smart enough to know that a DST boundary was crossed when I pass a timezone into DateTime creation.

Upvotes: 0

Views: 136

Answers (1)

Barmar
Barmar

Reputation: 780889

When you add whole days, PHP produces the same time of day, even if DST has changed. If you want to add a time interval without making this adjustment, you need to add hours rather than days. Multiply the number of days by 24 to get this.

$dateInterval = new \DateInterval('PT3600H'); // 3600 = 150*24

Upvotes: 2

Related Questions