spatie / opening-hours

Query and format a set of opening hours

Home Page:https://freek.dev/595-managing-opening-hours-with-php

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

commented

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.