<?php declare(strict_types=1); if (!function_exists('easter_date')) { /** * replacement for missing `easter_date` function * (!): Gregorian dates are fine, but only works * for Julian dates between 1900-2100 * * @param int $year * * @return false|int * @see https://stackoverflow.com/a/3589696 */ function easter_date(int $year): bool|int { return mktime( 0, 0, 0, (int)floor(($b = ($a = (19 * (($y = $year) % 19) + 15) % 30) + (2 * ($y % 4) + 4 * $y % 7 - $a + 34) % 7 + 114 ) / 31), ($b % 31) + 14, $y ); } } class FeastInfo { /** * determine feast-day info for given date (timestamp) * * @param $tDay int|null timestamp of day to check for feast-day info * @return array( * 'text' => '' Text * 'feast' => boolean true -> feast days * 'arState' => '' list of regions/federal states where this feast day applies, empty = all * ) * * list of regions/federal states * BW = Baden-Württemberg * BY = Bayern * BE = Berlin * BB = Brandenburg * HB = Bremen * HH = Hamburg * HE = Hessen * MV = Mecklenburg-Vorpommern * NI = Niedersachsen * NW = Nordrhein-Westfalen * RP = Rheinland-Pfalz * SL = Saarland * SN = Sachsen * ST = Sachsen-Anhalt * SH = Schleswig-Holstein * TH = Thüringen */ public static function getFeastInfo(int|null $tDay) { $md = date('md', $tDay); $tEaster = easter_date((int) date('Y', $tDay)); $feast = ''; $arState = []; // feast days per region if ($md === '0101') { $feast = trans('Neujahr'); } elseif ($md === '0501') { $feast = trans('Erster Mai'); } elseif ($md === '0106') { $feast = trans('Heiligen Drei Könige'); $arState = ['BW', 'BY', 'ST']; } elseif ($md === date('md', strtotime('-2 day', $tEaster))) { $feast = trans('Karfreitag'); } elseif ($md === date('md', $tEaster)) { $feast = trans('Ostersonntag'); } elseif ($md === date('md', strtotime('+1 day', $tEaster))) { $feast = trans('Ostermontag'); $arState = ['SN']; } elseif ($md === date('md', strtotime('+39 day', $tEaster))) { $feast = trans('Christi Himmelfahrt'); } elseif ($md === date('md', strtotime('+49 day', $tEaster))) { $feast = trans('Pfingstsonntag'); } elseif ($md === date('md', strtotime('+50 day', $tEaster))) { $feast = trans('Pfingstmontag'); } elseif ($md === date('md', strtotime('+60 day', $tEaster))) { $feast = trans('Fronleichnam'); $arState = ['BW', 'BY', 'HE', 'NW', 'RP', 'SL', 'SN', 'TH']; } elseif ($md === '0815') { $feast = trans('Maria Himmelfahrt'); $arState = ['SL', 'BY']; } elseif ($md === '1003') { $feast = trans('Tag der deutschen Einheit'); } elseif ($md === '1031') { $feast = trans('Reformationstag'); $arState = ['BB', 'MV', 'SN', 'ST', 'TH']; } elseif ($md === '1101') { $feast = trans('Allerheiligen'); $arState = ['BW', 'BY', 'NW', 'RP', 'SL']; } elseif ($md === date('md', strtotime('last wednesday', mktime(0, 0, 0, 11, 23, (int) date('Y', $tDay))))) { $feast = trans('Buß- und Bettag'); $arState = ['SN']; } elseif ($md === '1224') { $feast = trans('Heiliger Abend'); } elseif ($md === '1225') { $feast = trans('1. Weihnachtsfeiertag'); } elseif ($md === '1226') { $feast = trans('2. Weihnachtsfeiertag'); } elseif ($md === '1231') { $feast = trans('Silvester (Bankfeiertag)'); } elseif ($md === '0803') { $feast = trans('Internationaler Frauentag'); $arState = ['BE']; } $text = ''; if (date('N', $tDay) === '6') { $text = 'Samstag'; } elseif (date('N', $tDay) === '7') { $text = 'Sonntag'; } if (sizeof($arState) > 0) { $arStateMapping = [ 'BW' => 'Baden-Württemberg', 'BB' => 'Brandenburg', 'BY' => 'Bayern', 'BE' => 'Berlin', 'HB' => 'Bremen', 'HH' => 'Hamburg', 'HE' => 'Hessen' , 'MV' => 'Mecklenburg-Vorpommern', 'NI' => 'Niedersachsen', 'NW' => 'Nordrhein-Westfalen', 'RP' => 'Rheinland-Pfalz', 'SL' => 'Saarland', 'SN' => 'Sachsen', 'ST' => 'Sachsen-Anhalt', 'SH' => 'Schleswig-Holstein', 'TH' => 'Thüringen' ]; foreach ($arState as $k => $v) { $arState[$k] = $arStateMapping[$v]; } } if ($feast === '' && $text === '') { $text = 'Arbeitstag'; } elseif ($feast !== '' && $text !== '') { $text .= ' (' . $feast . rtrim(', ' . implode(', ', $arState), ' ,') . ')'; } elseif ($feast !== '') { $text = $feast . rtrim(', ' . implode(', ', $arState), ' ,'); } return [ 'text' => $text, 'feast' => ($feast !== ''), 'arState' => $arState ]; } /** * determine next non feast-day from given date * * @param int|null $tDay * * @return int|null */ public static function findNextWorkDay(int|null $tDay) { $fDay = self::getFeastInfo($tDay); if (($fDay['feast'] === true) || self::isWeekend($tDay)) { return self::findNextWorkDay($tDay + (24 * 60 * 60)); } return $tDay; } /** * determine last feast-day up to given date * * @param int|null $tDay * * @return int|null */ public static function findLastWorkDay(int|null $tDay) { $fDay = self::getFeastInfo($tDay); if (($fDay['feast'] === true) || self::isWeekend($tDay)) { return self::findLastWorkDay($tDay - (24 * 60 * 60)); } return $tDay; } /** * determine last feast-day up to given date * * @param int|null $tDay * * @return int|null */ public static function findLastFeastDay(int|null $tDay) { $fDay = self::getFeastInfo($tDay); if ($fDay['feast'] !== true) { return self::findLastFeastDay($tDay - (24 * 60 * 60)); } return $tDay; } /** * determine given day is a weekend day * * @param int|null $tDay * * @return bool */ public static function isWeekend(int|null $tDay) { return in_array((int) date('N', $tDay), [6, 7], true); } }