[[2026, 10, 23], 1, '1111100', [], [2026, 10, 26]], 'weekdays skip configured holiday' => [[2026, 10, 23], 1, '1111100', [[2026, 10, 26]], [2026, 10, 27]], 'Saturday enabled' => [[2026, 10, 23], 2, '1111110', [], [2026, 10, 24]], 'daily includes Sunday' => [[2026, 10, 24], 3, '1111111', [], [2026, 10, 25]], 'daily excludes configured holiday' => [[2026, 10, 24], 3, '1111111', [[2026, 10, 25]], [2026, 10, 26]], 'individual weekday mask' => [[2026, 10, 26], 1, '0010000', [], [2026, 10, 28]], 'weekly' => [[2026, 10, 26], 4, '', [], [2026, 11, 2]], 'weekly holiday moves forward' => [[2026, 10, 26], 4, '', [[2026, 11, 2], [2026, 11, 3]], [2026, 11, 4]], 'fortnightly' => [[2026, 10, 26], 5, '', [], [2026, 11, 9]], 'monthly clips short month' => [[2026, 1, 31], 6, '', [], [2026, 2, 28]], 'monthly clips leap month' => [[2024, 1, 31], 6, '', [], [2024, 2, 29]], 'monthly holiday moves forward' => [[2026, 1, 31], 6, '', [[2026, 2, 28]], [2026, 3, 1]], 'monthly year rollover' => [[2026, 12, 15], 6, '', [], [2027, 1, 15]], 'month end' => [[2026, 4, 12], 7, '', [], [2026, 5, 31]], 'month end holiday moves backward' => [[2026, 4, 12], 7, '', [[2026, 5, 31]], [2026, 5, 30]], 'half month from fifteenth' => [[2026, 4, 15], 8, '', [], [2026, 4, 30]], 'half month from month end' => [[2026, 4, 30], 8, '', [], [2026, 5, 15]], 'half month holiday moves backward' => [[2026, 4, 30], 8, '', [[2026, 5, 15]], [2026, 5, 14]], 'holiday only' => [[2026, 12, 23], 9, '0000000', [[2026, 12, 25]], [2026, 12, 25]], 'holiday or weekday: weekday sooner' => [[2026, 12, 23], 9, '1111100', [[2026, 12, 25]], [2026, 12, 24]], 'holiday or weekday: holiday sooner' => [[2026, 12, 23], 9, '0000001', [[2026, 12, 25]], [2026, 12, 25]], 'sixteenth from first' => [[2026, 4, 1], 10, '', [], [2026, 4, 16]], 'first from sixteenth' => [[2026, 4, 16], 10, '', [], [2026, 5, 1]], 'first holiday moves forward' => [[2026, 4, 16], 10, '', [[2026, 5, 1]], [2026, 5, 2]], 'four weeks over new year' => [[2026, 12, 15], 11, '', [], [2027, 1, 12]], 'four weeks holiday moves forward' => [[2026, 12, 15], 11, '', [[2027, 1, 12]], [2027, 1, 13]], 'DST spring keeps calendar day' => [[2026, 3, 28], 3, '1111111', [], [2026, 3, 29]], 'DST autumn keeps calendar day' => [[2026, 10, 24], 3, '1111111', [], [2026, 10, 25]], ]; } public function testHolidayLookupUsesExactDateFromConfiguredList(): void { $GLOBALS['ph'] = [[2026, 12, 25], [2026, 12, 26]]; self::assertTrue(isPublicHoliday(2026, 12, 25)); self::assertFalse(isPublicHoliday(2025, 12, 25)); self::assertFalse(isPublicHoliday(2026, 11, 25)); self::assertFalse(isPublicHoliday(2026, 12, 24)); } }