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

timezone is set on passed object when getting hours for a specific date

ragingdave opened this issue · comments

When calling forDate on the OpeningHours object, if the hours are in for example America/New_York, but the passed DateTimeInterface is in UTC, the result is that the passed object's timezone is changed unexpectedly. This appears to be in relation to a fix applied in #157 , as the timezone is applied directly to the passed object.

commented

Indeed, my recommendation in the meantime is to always work DateTimeImmutable instead of DateTime which is way safer as it avoids this kind of mess by creating copy instead of modifying the current object.

For the record, DateTime still exist in PHP just for backward compatibility. It is a design mistake, And date and time should always be represented in an immutable way.

Because actually mutable date-time makes no sense, you can't change a date. When $appointment->startDate changes, it's not semantically correct to say "Monday 8AM NY time becomes something else", no "Monday 8AM NY time" won't change, it's still the same for everybody, only your appointment change, and you actually set startDate to an other value.

$monday8AM = new DateTime('2022-07-25 08:00 America/New_York');
$appointment1->startDate = $monday8AM;
$appointment2->startDate = $monday8AM;
$appointment1->startDate->modify('2022-07-26 10:00 America/New_York');

You can see in this example that using DateTime does not properly reflect reality and lead to mistake.

Here $monday8AM get modified and $appointment2->startDate is affected by changing $appointment1->startDate.

Also there is no mutation of $appointment1 in the code.

DateTimeImmutable is a way better way to reflect the reality of date/time manipulation and lead to less mistakes:

$monday8AM = new DateTimeImmutable('2022-07-25 08:00 America/New_York');
$appointment1->startDate = $monday8AM;
$appointment2->startDate = $monday8AM;
$appointment1->startDate = $appointment1->startDate->modify('2022-07-26 10:00 America/New_York');

If we call modify (or setTimezone) it returns a new instance.

So here we don't mutate $monday8AM, $appointment2->startDate is unaffected and the mutation of $appointment1 becomes explicit.

Of course we should still fix support for DateTime in spatie/opening-hours

commented

Fixed in 2.11.3