nextOpen not respecting timezone
ragingdave opened this issue · comments
When calling nextOpen
or nextClose
, the resulting DateTime object (immutable or not) remains in the timezone of the passed DateTime (immutable or not). So as an example, calling nextOpen with a UTC DateTime instance, even if the OpeningHours are set for America/New_York
for example, the result will be the right time but the wrong timezone. As an example, if you might be expecting 8AM America/New_York, you actually get 8AM UTC for a given day.
Indeed, I can reproduce. I see the timezone feature was introduced for isOpenAt
#16, so only for the input. At this moment the library had no nextOpen
/ nextClose
method (no date to output).
I will investigate if we can fix it without causing breaking changes for users who might have a different usage.
Honestly I'm not keen on this timezone feature being embedded directly in spatie/opening-hours, you can get basically the same by just calling ->setTimezone()
on input/output and would have a greater and less ambiguous control this way and give OpeningHours
only the responsibility to check the times while ensuring the date timezones match the times of the definition:
$openingHours = \Spatie\OpeningHours\OpeningHours::create([
'monday' => ['09:00-12:00', '13:00-18:00'],
]); // Don't pass any timezone
function nextOpen(DateTimeImmutable $date): DateTimeImmutable {
global $openingHours;
$timezone = $date->getTimezone();
return $openingHours
->nextOpen($date->setTimezone(new DateTimeZone('America/New_York')))
->setTimezone($timezone); // Set back original timezone
}
$nextOpen = nextOpen(new DateTimeImmutable('2022-07-24 20:00 UTC'));
Basically you could even have a UTC input, opening-hours for a business in New York and let's say a remote user in Oslo:
$systemTimezone = 'UTC'; // Should always be UTC anyway :p
$businessSchedule = [
'monday' => ['09:00-12:00', '13:00-18:00'],
];
$businessTimezone = 'America/New_York'; // The one to use to read the schedule above
$userTimezone = 'Europe/Oslo'; // Coming from the browser
$openingHours = \Spatie\OpeningHours\OpeningHours::create($businessSchedule); // Don't pass any timezone
$now = new \DateTimeImmutable('now', new \DateTimeZone($systemTimezone));
$nexOpen = $openingHours->nextOpen($date->setTimezone(new \DateTimeZone($businessTimezone)));
$nextOpenForUser = $nextOpen->setTimezone(new \DateTimeZone($userTimezone));
echo 'You can call us after ' . $nextOpenForUser->format('H:i') . ' (local time)';
This last case makes me think using the same timezone for input and output would not actually be generally wanted, so I wonder if the implementation of the timezone for nextOpen
/ nextClose
method should only transform the input or also change back to original timezone the output.
Published in 2.12.0
You'll find some documentation about it on https://github.com/spatie/opening-hours#openinghourscreatearray-data-timezone--null-toutputtimezone--null-spatieopeninghoursopeninghours