src/BusinessTime/Schedule.php
<?php
namespace BusinessTime;
use BusinessTime\Exceptions\InvalidArgumentException;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Closure;
use ReflectionMethod;
use Spatie\OpeningHours\OpeningHours;
/**
* Create a schedule that won't apply globally nor enabling macro on Carbon and can later be called
* with any object.
*
* <autodoc generated by `composer types`>
*
* @method $this|null setOpeningHours(CarbonInterface $date, $openingHours) Set the opening hours for the class/instance.
* @method $this|null resetOpeningHours(CarbonInterface $date) Reset the opening hours for the class/instance.
* @method \Spatie\OpeningHours\OpeningHours getOpeningHours(CarbonInterface $date, $mode = null) Get the opening hours of the class/instance.
* @method mixed safeCallOnOpeningHours(CarbonInterface $date, $method, ...$arguments) Call a method on the OpeningHours of the current instance.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|bool getCalleeAsMethod(CarbonInterface $date, $method = null) Get a closure to be executed on OpeningHours on the current instance (or now if called globally) that should
* return a date, then convert it into a Carbon/sub-class instance.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface getMethodLoopOnHoliday(CarbonInterface $date) Loop on the current instance (or now if called statically) with a given method until it's not a holiday.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface getTernaryMethod(CarbonInterface $date) Get a method that return current date-time if $testMethod applied on it return true,
* else return the result of $method called on it.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addBusinessDays(CarbonInterface $date, $days = 1, $date = null) Add a given number of business days to the current date.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addBusinessDay(CarbonInterface $date, $days = 1, $date = null) Add one business day to the current date.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subBusinessDays(CarbonInterface $date, $days = 1, $date = null) Subtract a given number of business days to the current date.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subtractBusinessDays(CarbonInterface $date, $days = 1, $date = null) Subtract a given number of business days to the current date.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subBusinessDay(CarbonInterface $date, $days = 1, $date = null) Subtract one business day to the current date.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subtractBusinessDay(CarbonInterface $date, $days = 1, $date = null) Subtract one business day to the current date.
* @method int diffInBusinessDays(CarbonInterface $date, $other = null) Returns the difference between 2 dates in business days.
* @method int getBusinessDaysInMonth(CarbonInterface $date, $date = null) Get the number of business days in the current month.
* @method array getMonthBusinessDays(CarbonInterface $date, $date = null) Get list of date objects for each business day in the current month.
* @method $this|null setBusinessDayChecker(CarbonInterface $date, callable $checkCallback = null) Checks the date to see if it is a business day (neither a weekend day nor a holiday).
* @method bool isBusinessDay(CarbonInterface $date) Checks the date to see if it is a business day (extra workday or neither a weekend day nor a holiday).
* @method \Carbon\CarbonInterface|\Carbon\Carbon|\Carbon\CarbonImmutable nextBusinessDay(CarbonInterface $date) Sets the date to the next business day (neither a weekend day nor a holiday).
* @method \Carbon\CarbonInterface|\Carbon\Carbon|\Carbon\CarbonImmutable currentOrNextBusinessDay(CarbonInterface $date) Sets the date to the current or next business day (neither a weekend day nor a holiday).
* @method \Carbon\CarbonInterface|\Carbon\Carbon|\Carbon\CarbonImmutable previousBusinessDay(CarbonInterface $date) Sets the date to the previous business day (neither a weekend day nor a holiday).
* @method \Carbon\CarbonInterface|\Carbon\Carbon|\Carbon\CarbonImmutable currentOrPreviousBusinessDay(CarbonInterface $date) Sets the date to the current or previous business day.
* @method $this|null setObservedHolidaysZone(CarbonInterface $date, $zone, $self = null) Set the selected zone for observed holidays. So next observe methods will be saved and considered in this
* given custom zone.
* @method string|null getObservedHolidaysZone(CarbonInterface $date) Get the selected zone for observed holidays.
* @method $this|null setHolidayObserveStatus(CarbonInterface $date, $holidayId, $observed, $self = null) Set a holiday as observed/unobserved in the selected zone.
* @method $this|null getObserveHolidayMethod(CarbonInterface $date, $holidayId = null, $observed = null, $self = null) Set a holiday as observed/unobserved in the selected zone (can take array of holidays).
* @method $this|null observeHoliday(CarbonInterface $date, $holidayId = null, $observed = null, $self = null) Set a holiday as observed in the selected zone.
* @method $this|null unobserveHoliday(CarbonInterface $date, $holidayId = null, $observed = null, $self = null) Set a holiday as not observed in the selected zone.
* @method $this|null observeHolidays(CarbonInterface $date, $holidayId = null, $observed = null, $self = null) Set a holiday as observed in the selected zone.
* @method $this|null unobserveHolidays(CarbonInterface $date, $holidayId = null, $observed = null, $self = null) Set a holiday as not observed in the selected zone.
* @method $this|null observeAllHolidays(CarbonInterface $date, $holidayId = null, $observed = null, $self = null) Set all holidays as observed in the selected zone.
* @method $this|null unobserveAllHolidays(CarbonInterface $date, $holidayId = null, $observed = null, $self = null) Set all holidays as observed in the selected zone.
* @method bool checkObservedHoliday(CarbonInterface $date, $holidayId = null) Check if a given holiday ID is observed in the selected zone.
* @method bool isObservedHoliday(CarbonInterface $date, $holidayId = null, $date = null) Checks the date to see if it is a holiday observed in the selected zone.
* @method $this|null setHolidayGetter(CarbonInterface $date, callable $holidayGetter) Set the strategy to get the holiday ID from a date object.
* @method $this|null setExtraWorkdayGetter(CarbonInterface $date, callable $workdayGetter) Set the strategy to get the extra workday ID from a date object.
* @method string|false getDBDayId(CarbonInterface $date, string $getDays = 'getHolidays') Get the identifier of the current holiday or false if it's not a holiday.
* @method string|false getHolidayId(CarbonInterface $date) Get the identifier of the current holiday or false if it's not a holiday.
* @method bool isHoliday(CarbonInterface $date) Checks the date to see if it is a holiday.
* @method string|false getExtraWorkdayId(CarbonInterface $date) Get the identifier of the current special workday or false if it's not a special workday.
* @method bool isExtraWorkday(CarbonInterface $date) Checks the date to see if it is a holiday.
* @method array getHolidayNamesDictionary(CarbonInterface $date, $locale) Get the holidays in the given language.
* @method string|false getHolidayName(CarbonInterface $date, $date = null, $locale = null) Get the name of the current holiday (using the locale given in parameter or the current date locale)
* or false if it's not a holiday.
* @method array getYearHolidays(CarbonInterface $date, $year = null, $type = null, string $getDays = 'getHolidays') Get the holidays dates for a given year (current year if no parameter given).
* @method callable getYearHolidaysNextFunction(CarbonInterface $date, $year = null, $type = null, string $getDays = 'getHolidays') Get a next() callback to call to iterate over holidays of a year.
* @method string standardizeHolidaysRegion(CarbonInterface $date, $region) Return a standardized region name.
* @method array getHolidaysAvailableRegions(CarbonInterface $date) Get the current holidays region.
* @method mixed setHolidaysRegion(CarbonInterface $date, $region) Set the holidays region (see src/Cmixin/Holidays for examples).
* @method null|string getHolidaysRegion(CarbonInterface $date) Get the current holidays region.
* @method array getBDDaysList(CarbonInterface $date, string $list, $region = null) Get the holidays for the current region selected.
* @method array getHolidays(CarbonInterface $date, $region = null) Get the holidays for the current region selected.
* @method mixed setHolidays(CarbonInterface $date, $region, $holidays) Set the holidays list.
* @method array getExtraWorkdays(CarbonInterface $date, $region = null) Get the holidays for the current region selected.
* @method mixed setExtraWorkdays(CarbonInterface $date, $region, $holidays) Set the holidays list.
* @method mixed resetHolidays(CarbonInterface $date) Reset the holidays list.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|null pushToBDList(CarbonInterface $date, string $list, $region, $day, $dayId = null) Push a day into a given list list of a region.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|null pushHoliday(CarbonInterface $date, $region, $holiday, $holidayId = null) Push a holiday to the holidays list of a region.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|null pushWorkday(CarbonInterface $date, $region, $workday, $workdayId = null) Push a workday to the workdays list of a region.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|null setHolidayName(CarbonInterface $date, $holidayKey = null, $language = null, $name = null) Set/change the name of holiday by ID for a given language (or a list of languages).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|null addHoliday(CarbonInterface $date, $region, $holiday, $holidayId = null, $name = null, $observed = null) Add a holiday to the holidays list of a region and optionally init its ID, name and observed state.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|null addExtraWorkday(CarbonInterface $date, $region, $workday, $workdayId = null, $name = null) Add a workday to the workdays list of a region and optionally init its ID and name.
* @method array unpackHoliday(CarbonInterface $date, $holiday, $name = null, $observed = null) Unpack a holiday array definition.
* @method array checkHoliday(CarbonInterface $date, $holiday, $holidayId, $name = null, $observed = null) Check a holiday definition and unpack it if it's an array.
* @method mixed addHolidays(CarbonInterface $date, string $region, iterable $holidays = null, iterable $workingDays = null) Add a holiday to the holidays list of a region and optionally init their IDs, names and observed states (if provided as array-definitions).
* @method bool isDateTimeInstance(CarbonInterface $date, $value) Return true if the given value is a DateTime or DateTimeInterface.
* @method array swapDateTimeParam(CarbonInterface $date, $target, $date, $defaultValue) Store a first variable as Carbon instance into the second variable if the first one is a date.
* @method array|null getHolidayDataById(CarbonInterface $date, string $id) Get stored data set for the a given holiday ID.
* @method $this|null setHolidayDataById(CarbonInterface $date, string $id, array $data) Set stored data set for the a given holiday ID.
* @method array|null getHolidayData(CarbonInterface $date) Get stored data set for the current holiday or null if it's not a holiday.
* @method $this|null setHolidayData(CarbonInterface $date, array $data) Set stored data set for the current holiday, does nothing if it's not a holiday.
* @method mixed setMaxIteration(CarbonInterface $date, int $maximum) Set the maximum of loop turns to run before throwing an exception where trying to add
* or subtract open/closed time.
* @method mixed getMaxIteration(CarbonInterface $date) Get the maximum of loop turns to run before throwing an exception where trying to add
* or subtract open/closed time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface applyBusinessInterval(CarbonInterface $date, bool $inverted, bool $open, $interval = null, $unit = null, int $options = 0) Shift current time with a given interval taking into account only open time
* (if $open is true) or only closed time (if $open is false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addBusinessInterval(CarbonInterface $date, bool $open, $interval = null, $unit = null, int $options = 0) Add the given interval taking into account only open time
* (if $open is true) or only closed time (if $open is false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subBusinessInterval(CarbonInterface $date, bool $open, $interval = null, $unit = null, int $options = 0) Add the given interval taking into account only open time
* (if $open is true) or only closed time (if $open is false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addOpenTime(CarbonInterface $date, $interval = null, $unit = null, int $options = 0) Add the given interval taking into account only open time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subOpenTime(CarbonInterface $date, $interval = null, $unit = null, int $options = 0) Subtract the given interval taking into account only open time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addClosedTime(CarbonInterface $date, $interval = null, $unit = null, int $options = 0) Add the given interval taking into account only closed time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subClosedTime(CarbonInterface $date, $interval = null, $unit = null, int $options = 0) Subtract the given interval taking into account only closed time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addOpenMinutes(CarbonInterface $date, int $numberOfMinutes, int $options = 0) Add the given number of minutes taking into account only open time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subOpenMinutes(CarbonInterface $date, int $numberOfMinutes, int $options = 0) Subtract the given number of minutes taking into account only open time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addClosedMinutes(CarbonInterface $date, int $numberOfMinutes, int $options = 0) Add the given number of minutes taking into account only closed time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subClosedMinutes(CarbonInterface $date, int $numberOfMinutes, int $options = 0) Subtract the given number of minutes taking into account only closed time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addOpenHours(CarbonInterface $date, int $numberOfHours, int $options = 0) Add the given number of hours taking into account only open time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subOpenHours(CarbonInterface $date, int $numberOfHours, int $options = 0) Subtract the given number of hours taking into account only open time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface addClosedHours(CarbonInterface $date, int $numberOfHours, int $options = 0) Add the given number of hours taking into account only closed time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface subClosedHours(CarbonInterface $date, int $numberOfHours, int $options = 0) Subtract the given number of hours taking into account only closed time.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface closedOrNextOpenExcludingHolidays(CarbonInterface $date) Return current date-time if it's closed, else go to the next open date
* and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and closedOrNextOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface closedOrNextBusinessOpen(CarbonInterface $date) Return current date-time if it's closed, else go to the next open date
* and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and closedOrNextOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface closedOrPreviousBusinessOpen(CarbonInterface $date) Return current date-time if it's closed, else go to the previous open date
* and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and closedOrPreviousOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface closedOrPreviousOpenExcludingHolidays(CarbonInterface $date) Return current date-time if it's closed, else go to the previous open date
* and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and closedOrPreviousOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface closedOrNextOpen(CarbonInterface $date) Return current date-time if it's closed, else go to the next open date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface closedOrPreviousOpen(CarbonInterface $date) Return current date-time if it's closed, else go to the previous open date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrNextOpenExcludingHolidays(CarbonInterface $date) Return current date-time if it's open, else go to the next open date
* and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and currentOrNextOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrNextBusinessOpen(CarbonInterface $date) Return current date-time if it's open, else go to the next open date
* and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and currentOrNextOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrPreviousBusinessOpen(CarbonInterface $date) Return current date-time if it's open, else go to the previous open date
* and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and currentOrPreviousOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrPreviousOpenExcludingHolidays(CarbonInterface $date) Return current date-time if it's open, else go to the previous open
* date and time that is also not a holiday.
* Note than you can use the 'holidaysAreClosed' option and currentOrPreviousOpen().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrNextCloseIncludingHolidays(CarbonInterface $date) Return current date-time if it's closed, else go to the next close date
* and time or next holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and currentOrNextClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrNextBusinessClose(CarbonInterface $date) Return current date-time if it's closed, else go to the next close date
* and time or next holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and currentOrNextClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrPreviousCloseIncludingHolidays(CarbonInterface $date) Return current date-time if it's closed, else go to the previous close date
* and time or previous holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and currentOrPreviousClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrPreviousBusinessClose(CarbonInterface $date) Return current date-time if it's closed, else go to the previous close date
* and time or previous holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and currentOrPreviousClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrNextOpen(CarbonInterface $date) Return current date-time if it's open, else go to the next open date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrPreviousOpen(CarbonInterface $date) Return current date-time if it's open, else go to the previous open date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrNextClose(CarbonInterface $date) Return current date-time if it's closed, else go to the next close date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface currentOrPreviousClose(CarbonInterface $date) Return current date-time if it's closed, else go to the previous close date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Carbon\CarbonInterval|float diffInBusinessUnit(CarbonInterface $date, string $unit, $date = null, int $options = 0) Return an interval/count of given unit with open/closed business time between the current date and an other
* given date.
* @method \Carbon\CarbonInterval diffAsBusinessInterval(CarbonInterface $date, $date = null, int $options = 0) Return an interval with open/closed business time between the current date and an other
* given date.
* @method float diffInBusinessSeconds(CarbonInterface $date, $date = null, int $options = 0) Return a number of seconds with open/closed business time between the current date and an other
* given date.
* @method float diffInBusinessMinutes(CarbonInterface $date, $date = null, int $options = 0) Return a number of minutes with open/closed business time between the current date and an other
* given date.
* @method float diffInBusinessHours(CarbonInterface $date, $date = null, int $options = 0) Return a number of hours with open/closed business time between the current date and an other
* given date.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface nextOpenExcludingHolidays(CarbonInterface $date) Go to the next open date and time that is also not a holiday.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface nextBusinessOpen(CarbonInterface $date) Go to the next open date and time that is also not a holiday.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface previousOpenExcludingHolidays(CarbonInterface $date) Go to the previous open date and time that is also not a holiday.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface previousBusinessOpen(CarbonInterface $date) Go to the previous open date and time that is also not a holiday.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface nextCloseIncludingHolidays(CarbonInterface $date) Go to the next close date and time or next holiday if sooner.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface nextBusinessClose(CarbonInterface $date) Go to the next close date and time or next holiday if sooner.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface previousCloseIncludingHolidays(CarbonInterface $date) Go to the previous close date and time or previous holiday if sooner.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface previousBusinessClose(CarbonInterface $date) Go to the previous close date and time or previous holiday if sooner.
* @method bool isOpenOn($day) Returns true if the business is open on a given day according to current opening hours.
* @method bool isClosedOn($day) Returns true if the business is closed on a given day according to current opening hours.
* @method bool isOpen(CarbonInterface $date) Returns true if the business is open now (or current date and time) according to current opening hours.
* /!\ Important: it returns true if the current day is a holiday unless you set a closure handler for it in
* the exceptions setting.
* @method bool isClosed(CarbonInterface $date) Returns true if the business is closed now (or current date and time) according to current opening hours.
* /!\ Important: it returns false if the current day is a holiday unless you set a closure handler for it in
* the exceptions setting.
* @method bool isBusinessOpen(CarbonInterface $date) Returns true if the business is open and not a holiday now (or current date and time) according to current
* opening hours.
* @method bool isOpenExcludingHolidays(CarbonInterface $date) Returns true if the business is open and not a holiday now (or current date and time) according to current
* opening hours.
* @method bool isBusinessClosed(CarbonInterface $date) Returns true if the business is closed or a holiday now (or current date and time) according to current
* opening hours.
* @method bool isClosedIncludingHolidays(CarbonInterface $date) Returns true if the business is closed or a holiday now (or current date and time) according to current
* opening hours.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface nextOpen(CarbonInterface $date, $method = null) Go to the next open date and time.
* /!\ Important: holidays are assumed open unless you set a closure handler for it in the
* exceptions setting.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface nextClose(CarbonInterface $date, $method = null) Go to the next close date and time.
* /!\ Important: holidays are assumed open unless you set a closure handler for it in the
* exceptions setting.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface previousOpen(CarbonInterface $date, $method = null) Go to the previous open date and time.
* /!\ Important: holidays are assumed open unless you set a closure handler for it in the
* exceptions setting.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface previousClose(CarbonInterface $date, $method = null) Go to the previous close date and time.
* /!\ Important: holidays are assumed open unless you set a closure handler for it in the
* exceptions setting.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface openOrNextCloseIncludingHolidays(CarbonInterface $date) Return current date-time if it's open, else go to the next close date
* and time or next holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and openOrNextClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface openOrNextBusinessClose(CarbonInterface $date) Return current date-time if it's open, else go to the next close date
* and time or next holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and openOrNextClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface openOrPreviousCloseIncludingHolidays(CarbonInterface $date) Return current date-time if it's open, else go to the previous close date
* and time or previous holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and openOrPreviousClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface openOrPreviousBusinessClose(CarbonInterface $date) Return current date-time if it's open, else go to the previous close date
* and time or previous holiday if sooner.
* Note than you can use the 'holidaysAreClosed' option and openOrPreviousClose().
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface openOrNextClose(CarbonInterface $date) Return current date-time if it's open, else go to the next close date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface openOrPreviousClose(CarbonInterface $date) Return current date-time if it's open, else go to the previous close date and time
* (holidays ignored if not set as exception and holidaysAreClosed set to false).
* @method \Spatie\OpeningHours\OpeningHoursForDay getCurrentDayOpeningHours(CarbonInterface $date) Get OpeningHoursForDay instance of the current instance or class.
* @method \Spatie\OpeningHours\TimeRange[] getCurrentOpenTimeRanges(CarbonInterface $date) Get open time ranges as array of TimeRange instances that matches the current date and time.
* @method \Spatie\OpeningHours\TimeRange|bool getCurrentOpenTimeRange(CarbonInterface $date) Get current open time range as TimeRange instance or false if closed.
* @method \Carbon\CarbonPeriod|bool getCurrentOpenTimePeriod(CarbonInterface $date, $interval = null) Get current open time range as TimeRange instance or false if closed.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|bool getCurrentOpenTimeRangeStart(CarbonInterface $date, $method = null) Get current open time range start as Carbon instance or false if closed.
* /!\ Important: it returns true if the current day is a holiday unless you set a closure handler for it in
* the exceptions setting.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|bool getCurrentOpenTimeRangeEnd(CarbonInterface $date, $method = null) Get current open time range end as Carbon instance or false if closed.
* /!\ Important: it returns true if the current day is a holiday unless you set a closure handler for it in
* the exceptions setting.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|bool getCurrentBusinessTimeRangeStart(CarbonInterface $date, $method = null) Get current open time range start as Carbon instance or false if closed or holiday.
* @method \Carbon\Carbon|\Carbon\CarbonImmutable|\Carbon\CarbonInterface|bool getCurrentBusinessOpenTimeRangeEnd(CarbonInterface $date, $method = null) Get current open time range end as Carbon instance or false if closed.
*</autodoc>
*/
final class Schedule
{
/**
* @var BusinessTimeWrapper
*/
private $businessTime;
/**
* @var array
*/
private $bindMacroContext = [];
private function __construct(BusinessTimeWrapper $businessTime)
{
$this->businessTime = $businessTime;
}
public static function create(array $openingHours): self
{
return new self(BusinessTimeWrapper::create($openingHours));
}
/**
* @param string|int $day
*
* @return string
*/
public function normalizeDay($day): string
{
return $this->businessTime->normalizeDay()($day);
}
public function convertOpeningHours($defaultOpeningHours, $data = null): OpeningHours
{
return $this->businessTime->convertOpeningHours()($defaultOpeningHours, $data);
}
public function __call(string $name, array $arguments)
{
$closure = $this->businessTime->$name();
if (!($closure instanceof Closure)) {
throw new InvalidArgumentException(
$name.' cannot be called on a '.self::class.'.'
);
}
$arguments = array_map(function ($value) {
return ($value instanceof CarbonInterface)
? $this->passBusinessTimeMethods($value)
: $value;
}, $arguments);
$initialArguments = $arguments;
$date = array_shift($arguments);
if (!($date instanceof CarbonInterface)) {
$arguments = $initialArguments;
$date = $this->passBusinessTimeMethods(CarbonImmutable::now());
}
return $this->callInMacroContext($date, $closure, $arguments);
}
private function passBusinessTimeMethods(CarbonInterface $date): CarbonInterface
{
if (!$date->isMutable()) {
$date = $date->copy();
}
return $date->settings(['macros' => $this->businessTime->getMethods()]);
}
private function callInMacroContext(CarbonInterface $date, Closure $closure, array $arguments)
{
$class = get_class($date);
return $this->callInContext(
$this->getBindMacroContext($class),
$date,
$closure->bindTo(null, $class),
$arguments
);
}
private function callInContext(
?ReflectionMethod $context,
CarbonInterface $date,
Closure $closure,
array $arguments
) {
if (!$context) {
return $closure(...$arguments);
}
return $context->invoke(null, $date, static function () use ($closure, $arguments) {
return $closure(...$arguments);
});
}
private function getBindMacroContext(string $class): ?ReflectionMethod
{
if (array_key_exists($class, $this->bindMacroContext)) {
return $this->bindMacroContext[$class];
}
$bindMacroContextMethod = $this->calculateBindMacroContext($class);
$this->bindMacroContext[$class] = $bindMacroContextMethod;
return $bindMacroContextMethod;
}
private function calculateBindMacroContext(string $class): ?ReflectionMethod
{
if (!method_exists($class, 'bindMacroContext')) {
return null;
}
$bindMacroContextMethod = new ReflectionMethod($class, 'bindMacroContext');
if (PHP_VERSION < 8.1) {
$bindMacroContextMethod->setAccessible(true); // @codeCoverageIgnore
}
return $bindMacroContextMethod;
}
}