spatie / holidays
Calculate public holidays
Fund package maintenance!
Requires
- php: ^8.4
- ext-calendar: *
- ext-intl: *
- nesbot/carbon: ^3.0
Requires (Dev)
- laravel/pint: ^1.0
- laravel/prompts: ^0.3.0
- pestphp/pest: ^4.0
- phpstan/phpstan: ^2.0
- rector/rector: ^2.0
- spatie/invade: ^2.0
- spatie/ray: ^1.40.1
- symfony/var-dumper: ^8.0
- dev-main
- 2.0.3
- 2.0.2
- 2.0.1
- 2.0.0
- v1.x-dev
- 1.24.0
- 1.23.0
- 1.22.1
- 1.22.0
- 1.21.0
- 1.20.0
- 1.19.0
- 1.18.0
- 1.17.3
- 1.17.2
- 1.17.1
- 1.17.0
- 1.16.0
- 1.15.0
- 1.14.1
- 1.14.0
- 1.13.1
- 1.13.0
- 1.12.0
- 1.11.0
- 1.10.0
- 1.9.1
- 1.9.0
- 1.8.0
- 1.7.0
- 1.6.1
- 1.6.0
- 1.5.1
- 1.5.0
- 1.4.0
- 1.3.0
- 1.2.0
- 1.1.0
- 1.0.2
- 1.0.1
- 1.0.0
- 0.0.2
- 0.0.1
- dev-dependabot/github_actions/dependabot/fetch-metadata-3.1.0
This package is auto-updated.
Last update: 2026-04-20 17:43:11 UTC
README
This package can calculate public holidays for a country.
use Spatie\Holidays\Holidays; $holidays = Holidays::for('be')->get(); $holidays[0]->name; // 'Nieuwjaar' $holidays[0]->date; // CarbonImmutable('2024-01-01') $holidays[0]->type; // HolidayType::National
Support us
We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.
We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.
Installation
You can install the package via composer:
composer require spatie/holidays
This package requires PHP 8.4+.
Supported countries
We support the countries listed in this directory. If you want to add a country, please create a pull request. See Adding a new country for a guide.
Usage
You can get all holidays for a country by using the get method. It returns an array of Holiday objects.
use Spatie\Holidays\Holidays; $holidays = Holidays::for('be')->get(); foreach ($holidays as $holiday) { $holiday->name; // 'Nieuwjaar' $holiday->date; // CarbonImmutable instance $holiday->type; // HolidayType::National }
You can pass a country instance or an ISO 3166-1 alpha-2 code:
use Spatie\Holidays\Countries\Belgium; $holidays = Holidays::for(Belgium::make())->get(); $holidays = Holidays::for('be')->get();
The Holiday object implements JsonSerializable:
json_encode($holidays[0]); // {"name":"Nieuwjaar","date":"2024-01-01","type":"national","region":null}
Getting holidays for a specific year
$holidays = Holidays::for(country: 'be', year: 2024)->get();
Getting holidays between two dates
The getInRange method returns all holidays between two dates (inclusive). Dates are swappable — the lower date is always used as the start.
$holidays = Holidays::for('be')->getInRange('2024-01-01', '2024-12-31');
You can also use shorthand formats:
$holidays = Holidays::for('be')->getInRange('2024', '2025'); // full years $holidays = Holidays::for('be')->getInRange('2024-06', '2025-05'); // year-month
Getting holidays in a specific language
$holidays = Holidays::for(country: 'be', locale: 'fr')->get();
If no translation file exists for the given locale, the original holiday names are returned.
Regional holidays
Some countries have region-specific holidays. You can pass a region code to the for method:
$holidays = Holidays::for('de', year: 2024, region: 'DE-BW')->get();
Or use the country class directly:
use Spatie\Holidays\Countries\Germany; $holidays = Holidays::for(Germany::make('DE-BW'), year: 2024)->get();
To discover which regions a country supports:
use Spatie\Holidays\Countries\Germany; Germany::regions(); // ['DE-BW', 'DE-BY', 'DE-BE', ...]
Countries that support regions: Australia, Bosnia and Herzegovina, France, Germany, Malaysia, Spain, Switzerland.
Determining if a date is a holiday
Holidays::for('be')->isHoliday('2024-01-01'); // true
Determining if today is a holiday
Holidays::for('be')->isTodayHoliday(); // true or false
Getting upcoming holidays
$holidays = Holidays::for('be')->getUpcoming(3); // Returns the next 3 upcoming holidays foreach ($holidays as $holiday) { echo $holiday->date; // CarbonImmutable echo $holiday->name; }
Getting long weekends
$longWeekends = Holidays::for('de', 2024)->getLongWeekends(); // With custom minimum days (default: 4) $longWeekends = Holidays::for('de', 2024)->getLongWeekends(3); foreach ($longWeekends as $weekend) { echo $weekend->startDate; // First day of the long weekend echo $weekend->endDate; // Last day of the long weekend echo $weekend->dayCount; // Number of days echo $weekend->holidays; // Array of Holiday objects }
Getting the name of a holiday
Holidays::for('be')->getName('2024-01-01'); // 'Nieuwjaar'
Determining whether a country is supported
Holidays::has('be'); // true Holidays::has('unknown'); // false
Adding a new country
This is a community driven package. If you find any errors, please create a pull request with the fix, or at least open an issue.
Basic country
Create a new class in src/Countries that extends Country. At minimum, you need to implement countryCode() and allHolidays():
use Spatie\Holidays\Countries\Country; use Spatie\Holidays\Holiday; use Spatie\Holidays\HolidayType; class MyCountry extends Country { public function countryCode(): string { return 'xx'; // ISO 3166-1 alpha-2 code } protected function allHolidays(int $year): array { return [ Holiday::national("New Year's Day", "{$year}-01-01"), Holiday::national('Christmas', "{$year}-12-25"), ]; } }
The Holiday::national() helper accepts both strings and CarbonImmutable instances. For Easter-based holidays, use the easter() or orthodoxEaster() helpers:
protected function allHolidays(int $year): array { $easter = $this->easter($year); return [ Holiday::national('Good Friday', $easter->subDays(2)), Holiday::national('Easter Monday', $easter->addDay()), ]; }
For relative dates, use CarbonImmutable::parse():
Holiday::national('Labor Day', CarbonImmutable::parse("first monday of September {$year}"));
If your country defines holidays in a non-English language, override defaultLocale():
protected function defaultLocale(): string { return 'de'; }
Register your country
In src/CountryRegistry.php, add your ISO country code and country class to the MAP constant.
Regional holidays
If your country has region-specific holidays, implement the HasRegions interface:
use Spatie\Holidays\Contracts\HasRegions; use Spatie\Holidays\Exceptions\InvalidRegion; class MyCountry extends Country implements HasRegions { protected function __construct(protected ?string $region = null) { if ($region !== null && ! in_array($region, static::regions())) { throw InvalidRegion::notFound($region); } } public static function regions(): array { return ['XX-A', 'XX-B', 'XX-C']; } public function region(): ?string { return $this->region; } protected function allHolidays(int $year): array { return array_merge( $this->nationalHolidays($year), $this->regionHolidays($year), ); } protected function regionHolidays(int $year): array { return match ($this->region) { 'XX-A' => ['Regional Day' => CarbonImmutable::createFromDate($year, 6, 1)], default => [], }; } }
Observed holidays
If your country moves holidays that fall on a weekend to the next weekday, use the HasObservedHolidays trait:
use Spatie\Holidays\Concerns\HasObservedHolidays; use Spatie\Holidays\Holiday; class MyCountry extends Country { use HasObservedHolidays; protected function allHolidays(int $year): array { $holidays = [ Holiday::national("New Year's Day", "{$year}-01-01"), ]; // Example: if New Year's Day falls on a weekend, add an observed day $newYear = $this->sundayToNextMonday($holidays[0]->date); if ($newYear !== null) { $holidays[] = Holiday::observed("New Year's Day (Observed)", $newYear); } return $holidays; } }
The trait provides these methods (each returns null if no shift applies):
weekendToNextMonday(CarbonInterface $date)— shifts Saturday/Sunday to MondaysundayToNextMonday(CarbonInterface $date)— shifts Sunday to MondayobservedChristmasDay(CarbonInterface $date)— Saturday to Monday, Sunday to TuesdayobservedBoxingDay(CarbonInterface $date)— Saturday to Monday, Sunday to Tuesday
Holiday types
The Holiday class supports different holiday types:
use Spatie\Holidays\Holiday; use Spatie\Holidays\HolidayType; Holiday::national('New Year', "{$year}-01-01"); // Default type Holiday::regional('Regional Day', "{$year}-06-01", 'XX-RE'); // With region Holiday::religious('Easter', $easterDate); // Religious holidays Holiday::observed('Observed Day', $observedDate); // Observed holidays Holiday::banked('Bank Holiday', "{$year}-12-25"); // Bank holidays
Available types in HolidayType enum: National, Regional, Religious, Observed, Banked.
Calendar systems
For countries that use Islamic, Chinese, Indian, or Nepali calendar dates, use the corresponding calendar trait. These traits rely on precomputed lookup tables defined as protected const arrays on your country class:
use Spatie\Holidays\Calendars\IslamicCalendar; use Spatie\Holidays\Contracts\Islamic; class MyCountry extends Country implements Islamic { use IslamicCalendar; protected const eidAlFitr = [ 2024 => '04-10', 2025 => '03-30', // ... ]; protected const eidAlAdha = [ 2024 => '06-16', 2025 => '06-06', // ... ]; }
Countries with lookup tables must declare their supported year range:
protected function supportedYearRange(): array { return [2024, 2037]; // [min, max] based on your lookup data }
For multi-day holidays (like Eid), use convertPeriods() to expand a CarbonPeriod into individual named days:
$this->convertPeriods('Eid al-Fitr', $year, $this->eidAlFitr($year)[0], includeEve: true);
Available calendar traits: IslamicCalendar, ChineseCalendar, IndianCalendar, NepaliCalendar.
Translations
To add translations for a country, create a JSON file at lang/{countryCode}/{locale}/holidays.json:
{
"New Year's Day": "Jour de l'An",
"Christmas": "Noël"
}
The keys must match the holiday names returned by allHolidays().
Testing
- Create a test file in
tests/Countries/:
use Carbon\CarbonImmutable; use Spatie\Holidays\Holidays; it('can calculate my country holidays', function () { CarbonImmutable::setTestNow('2024-01-01'); $holidays = Holidays::for(country: 'xx')->get(); expect($holidays) ->toBeArray() ->not()->toBeEmpty(); expect(formatDates($holidays))->toMatchSnapshot(); });
- Run
vendor/bin/pest --update-snapshotsto generate the snapshot. - Verify the generated snapshot in
tests/.pest/snapshots/is correct.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Upgrading
Please see UPGRADING for how to upgrade to a new major version.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.