diff --git a/src/Concerns/Observable.php b/src/Concerns/Observable.php new file mode 100644 index 000000000..52342c6fe --- /dev/null +++ b/src/Concerns/Observable.php @@ -0,0 +1,54 @@ +startOfDay(); + + return match ($christmasDay->dayName) { + 'Saturday' => $christmasDay->next('monday'), + 'Sunday' => $christmasDay->next('tuesday'), + default => null, + }; + } + + protected function observedBoxingDay(int $year): ?CarbonInterface + { + $christmasDay = (new CarbonImmutable($year.'-12-25'))->startOfDay(); + $boxingDay = $christmasDay->addDay(); + + return match ($christmasDay->dayName) { + 'Friday' => $boxingDay->next('monday'), + 'Saturday' => $boxingDay->next('tuesday'), + default => null, + }; + } + + protected function weekendToNextMonday(string|CarbonInterface $date, int $year): ?CarbonInterface + { + if (is_string($date)) { + $date = CarbonImmutable::createFromFormat('Y-m-d', "{$year}-{$date}")->startOfDay(); + } + + if ($date->isWeekend()) { + return $date->next('monday'); + } + + return null; + } + + protected function sundayToNextMonday(CarbonInterface $date): ?CarbonInterface + { + if ($date->isSunday()) { + return $date->next('monday'); + } + + return null; + } +} diff --git a/src/Countries/Ghana.php b/src/Countries/Ghana.php index 08951f1a5..2e9ed2d2d 100644 --- a/src/Countries/Ghana.php +++ b/src/Countries/Ghana.php @@ -4,9 +4,12 @@ use Carbon\CarbonImmutable; use Carbon\CarbonInterface; +use Spatie\Holidays\Concerns\Observable; class Ghana extends Country { + use Observable; + public function countryCode(): string { return 'gh'; @@ -20,7 +23,7 @@ protected function allHolidays(int $year): array ); } - /** @return array */ + /** @return array */ protected function observedHolidays(int $year): array { $holidays = [ @@ -30,16 +33,23 @@ protected function observedHolidays(int $year): array 'May Day' => '05-01', 'Founder\'s Day' => '08-04', 'Kwame Nkrumah Memorial Day' => '09-21', + 'Christmas Day' => '12-25', + 'Boxing Day' => '12-26', ]; - $holidays = array_map(function ($holiday) use ($year) { - return $this->observed($holiday, $year); - }, $holidays); + foreach ($holidays as $name => $date) { + $observedDay = match ($name) { + 'Christmas Day' => $this->observedChristmasDay($year), + 'Boxing Day' => $this->observedBoxingDay($year), + default => $this->weekendToNextMonday($date, $year), + }; + + if ($observedDay) { + $holidays[$name] = $observedDay; + } + } - return array_merge($holidays, [ - 'Christmas Day' => $this->observedChristmasDay($year), - 'Boxing Day' => $this->observedBoxingDay($year), - ]); + return $holidays; } protected function observed(string $date, int $year): CarbonInterface @@ -53,34 +63,6 @@ protected function observed(string $date, int $year): CarbonInterface return $holiday; } - protected function christmas(int $year): CarbonInterface - { - return (new CarbonImmutable($year.'-12-25'))->startOfDay(); - } - - protected function observedChristmasDay(int $year): CarbonInterface - { - $christmasDay = $this->christmas($year); - - return match ($christmasDay->dayName) { - 'Saturday' => $christmasDay->next('monday'), - 'Sunday' => $christmasDay->next('tuesday'), - default => $christmasDay, - }; - } - - protected function observedBoxingDay(int $year): CarbonInterface - { - $christmasDay = $this->christmas($year); - $boxingDay = new CarbonImmutable($year.'-12-26'); - - return match ($christmasDay->dayName) { - 'Friday' => $boxingDay->next('monday'), - 'Saturday' => $boxingDay->next('tuesday'), - default => $boxingDay, - }; - } - /** @return array */ protected function variableHolidays(int $year): array { diff --git a/src/Countries/Ireland.php b/src/Countries/Ireland.php index 9478a026a..092bfdbdc 100644 --- a/src/Countries/Ireland.php +++ b/src/Countries/Ireland.php @@ -16,10 +16,6 @@ protected function allHolidays(int $year): array return array_merge([ 'New Year\'s Day' => '01-01', 'Saint Patrick\'s Day' => '03-17', - 'May Public Holiday' => 'first monday of May', - 'June Public Holiday' => 'first monday of June', - 'August Public Holiday' => 'first monday of August', - 'October Public Holiday' => 'last monday of October', 'Christmas Day' => '12-25', 'Saint Stephen\'s Day' => '12-26', ], $this->variableHolidays($year)); @@ -28,10 +24,12 @@ protected function allHolidays(int $year): array /** @return array */ protected function variableHolidays(int $year): array { - $easter = $this->easter($year); - $variableHolidays = [ 'Easter Monday' => $this->easter($year)->addDay(), + 'May Public Holiday' => 'first monday of May', + 'June Public Holiday' => 'first monday of June', + 'August Public Holiday' => 'first monday of August', + 'October Public Holiday' => 'last monday of October', ]; if ($year >= 2023) { diff --git a/src/Countries/Japan.php b/src/Countries/Japan.php index 455c9c7b8..3f00fdf29 100644 --- a/src/Countries/Japan.php +++ b/src/Countries/Japan.php @@ -2,6 +2,8 @@ namespace Spatie\Holidays\Countries; +use Carbon\CarbonImmutable; + class Japan extends Country { public function countryCode(): string @@ -11,9 +13,8 @@ public function countryCode(): string protected function allHolidays(int $year): array { - return [ + return array_merge([ '元日' => '01-01', // New Year's Day - '成人の日' => 'second monday of january', '建国記念の日' => '02-11', // Foundation Day '天皇誕生日' => '02-23', // Emperor's Birthday '春分の日' => '03-20', // Vernal Equinox Day *Decided each year; rarely on 03-21 @@ -21,14 +22,22 @@ protected function allHolidays(int $year): array '憲法記念日' => '05-03', // Constitution Day 'みどりの日' => '05-04', // Greenery Day 'こどもの日' => '05-05', // Children's Day - '海の日' => 'third monday of july', '山の日' => '08-11', // Mountain Day - '敬老の日' => 'third monday of september', '秋分の日' => '09-23', // Autumnal Equinox Day *Decided each year; rarely on 09-22 - 'スポーツの日' => 'second monday of october', '文化の日' => '11-03', // Culture Day '勤労感謝の日' => '11-23', // Labor Thanksgiving Day + ], $this->variableHolidays()); + } + + /** @return array */ + protected function variableHolidays(): array + { + return [ + '成人の日' => 'second monday of january', + '海の日' => 'third monday of july', + '敬老の日' => 'third monday of september', + 'スポーツの日' => 'second monday of october', ]; } } diff --git a/src/Countries/NorthernIreland.php b/src/Countries/NorthernIreland.php index 4bdbf2c1f..c5c30a2c3 100644 --- a/src/Countries/NorthernIreland.php +++ b/src/Countries/NorthernIreland.php @@ -20,8 +20,8 @@ protected function allHolidays(int $year): array $this->earlyMayBankHoliday($year), $this->battleOfTheBoyne($year), [ - 'Spring bank holiday' => new CarbonImmutable("last monday of may {$year}", 'Europe/London'), - 'Summer bank holiday' => new CarbonImmutable("last monday of august {$year}", 'Europe/London'), + 'Spring bank holiday' => 'last monday of may', + 'Summer bank holiday' => 'last monday of august', ], $this->christmasDay($year), $this->boxingDay($year), diff --git a/src/Countries/Wales.php b/src/Countries/Wales.php index 33e1ca3b8..f2ebc8612 100644 --- a/src/Countries/Wales.php +++ b/src/Countries/Wales.php @@ -4,130 +4,96 @@ use Carbon\CarbonImmutable; use Carbon\CarbonInterface; +use Spatie\Holidays\Concerns\Observable; class Wales extends Country { + use Observable; + public function countryCode(): string { return 'gb-cym'; } - /** @return array */ - protected function christmasDay(int $year): array + /** @return array */ + protected function allHolidays(int $year): array { - $christmasDay = new CarbonImmutable($year.'-12-25', 'Europe/London'); - $key = 'Christmas Day'; - - if ($christmasDay->isSaturday()) { - $key .= ' (substitute day)'; - $christmasDay = $christmasDay->next('monday'); - } - - if ($christmasDay->isSunday()) { - $key .= ' (substitute day)'; - $christmasDay = $christmasDay->next('tuesday'); - } - - return [$key => $christmasDay]; + return array_merge( + $this->observedHolidays($year), + $this->earlyMayBankHoliday($year), + $this->variableHolidays($year), + $this->oneOffHolidays($year), + ); } - /** @return array */ - protected function boxingDay(int $year): array + /** @return array */ + protected function observedHolidays(int $year): array { - $christmasDay = new CarbonImmutable($year.'-12-25', 'Europe/London'); - $boxingDay = new CarbonImmutable($year.'-12-26', 'Europe/London'); - $key = 'Boxing Day'; - - if ($christmasDay->isFriday()) { - $key .= ' (substitute day)'; - $boxingDay = $boxingDay->next('monday'); - } + $holidays = [ + 'New Year\'s Day' => '01-01', + 'Christmas Day' => '12-25', + 'Boxing Day' => '12-26', + ]; - if ($christmasDay->isSaturday()) { - $key .= ' (substitute day)'; - $boxingDay = $boxingDay->next('tuesday'); + foreach ($holidays as $name => $date) { + $observedDay = match ($name) { + 'Christmas Day' => $this->observedChristmasDay($year), + 'Boxing Day' => $this->observedBoxingDay($year), + default => $this->weekendToNextMonday($date, $year), + }; + + if ($observedDay) { + $holidays[$name.' (substitute day)'] = $observedDay; + unset($holidays[$name]); + } } - return [$key => $boxingDay]; + return $holidays; } - /** @return array */ - protected function newYearsDay(int $year): array + /** @return array */ + protected function variableHolidays(int $year): array { - $newYearsDay = new CarbonImmutable($year.'-01-01', 'Europe/London'); - $key = 'New Year\'s Day'; + $easterSunday = $this->easter($year); - if ($newYearsDay->isWeekend()) { - $key .= ' (substitute day)'; - $newYearsDay = $newYearsDay->next('monday'); - } + $goodFriday = $easterSunday->subDays(2); + $easterMonday = $easterSunday->addDay(); - return [$key => $newYearsDay]; + return [ + 'Good Friday' => $goodFriday, + 'Easter Monday' => $easterMonday, + 'Spring bank holiday' => 'last monday of may', + 'Summer bank holiday' => 'last monday of august', + ]; } - /** @return array */ + /** @return array */ protected function earlyMayBankHoliday(int $year): array { if ($year === 2020) { return [ - 'Early May bank holiday (VE day)' => new CarbonImmutable('2020-05-08', 'Europe/London'), + 'Early May bank holiday (VE day)' => (new CarbonImmutable('2020-05-08'))->startOfDay(), ]; } if ($year === 2023) { return [ - 'Bank holiday for the coronation of King Charles III' => new CarbonImmutable('2020-05-08', 'Europe/London'), + 'Bank holiday for the coronation of King Charles III' => (new CarbonImmutable('2020-05-08'))->startOfDay(), ]; } - return ['Early May bank holiday' => new CarbonImmutable("first monday of may {$year}", 'Europe/London')]; + return ['Early May bank holiday' => 'first monday of may']; } - /** - * @return array|CarbonImmutable[] - */ + /** @return array */ protected function oneOffHolidays(int $year): array { return match ($year) { 2022 => [ - 'Platinum Jubilee bank holiday' => new CarbonImmutable('2022-06-03', 'Europe/London'), - 'Bank Holiday for the State Funeral of Queen Elizabeth II' => new CarbonImmutable('2022-09-19', 'Europe/London'), + 'Platinum Jubilee bank holiday' => (new CarbonImmutable('2022-06-03'))->startOfDay(), + 'Bank Holiday for the State Funeral of Queen Elizabeth II' => (new CarbonImmutable('2022-09-19'))->startOfDay(), ], default => [], }; } - - /** @return array */ - protected function allHolidays(int $year): array - { - $regularHolidays = array_merge( - $this->newYearsDay($year), - $this->earlyMayBankHoliday($year), - [ - 'Spring bank holiday' => new CarbonImmutable("last monday of may {$year}", 'Europe/London'), - 'Summer bank holiday' => new CarbonImmutable("last monday of august {$year}", 'Europe/London'), - ], - $this->christmasDay($year), - $this->boxingDay($year), - $this->variableHolidays($year) - ); - - $oneOffHolidays = $this->oneOffHolidays($year); - - return array_merge($regularHolidays, $oneOffHolidays); - } - - /** @return array */ - protected function variableHolidays(int $year): array - { - $easterSunday = $this->easter($year); - - $goodFriday = $easterSunday->subDays(2); - $easterMonday = $easterSunday->addDay(); - - return [ - 'Good Friday' => $goodFriday, - 'Easter Monday' => $easterMonday, - ]; - } }