PHPackages                             spatie/holidays - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. spatie/holidays

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

spatie/holidays
===============

Calculate public holidays

2.3.0(3w ago)402860.1k↓19.6%2081MITPHPPHP ^8.4CI passing

Since Jan 15Pushed 1w ago4 watchersCompare

[ Source](https://github.com/spatie/holidays)[ Packagist](https://packagist.org/packages/spatie/holidays)[ Docs](https://github.com/spatie/holidays)[ GitHub Sponsors](https://github.com/spatie)[ RSS](/packages/spatie-holidays/feed)WikiDiscussions main Synced 4d ago

READMEChangelog (10)Dependencies (36)Versions (49)Used By (1)

Calculate public holidays for a country
=======================================

[](#calculate-public-holidays-for-a-country)

[![Latest Version on Packagist](https://camo.githubusercontent.com/cb4e70f321658e94927a61b9c4b83f97daee6d80f3d6fa9183f610eedc333c21/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f686f6c69646179732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/holidays)[![Tests](https://github.com/spatie/holidays/actions/workflows/run-tests.yml/badge.svg)](https://github.com/spatie/holidays/actions/workflows/run-tests.yml)[![Total Downloads](https://camo.githubusercontent.com/4a2dcdeabb68007da85320946077ec0b31f5d27f75b97197fdc1ed4c2a6bdfee/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f686f6c69646179732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/holidays)

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
----------

[](#support-us)

[![](https://camo.githubusercontent.com/3adb44be83886be291891f152eac98653020672667ddf685008564e737ac470e/68747470733a2f2f6769746875622d6164732e73332e65752d63656e7472616c2d312e616d617a6f6e6177732e636f6d2f686f6c69646179732e6a70673f743d31)](https://spatie.be/github-ad-click/holidays)

We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).

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](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require spatie/holidays
```

This package requires PHP 8.4+.

Supported countries
-------------------

[](#supported-countries)

We support the countries listed in [this directory](https://github.com/spatie/holidays/tree/main/src/Countries). If you want to add a country, please create a pull request. See [Adding a new country](#adding-a-new-country) for a guide.

Usage
-----

[](#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](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 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

[](#getting-holidays-for-a-specific-year)

```
$holidays = Holidays::for(country: 'be', year: 2024)->get();
```

### Getting holidays between two dates

[](#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

[](#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

[](#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, Brazil, France, Germany, Malaysia, Spain, Switzerland.

### Determining if a date is a holiday

[](#determining-if-a-date-is-a-holiday)

```
Holidays::for('be')->isHoliday('2024-01-01'); // true
```

### Determining if today is a holiday

[](#determining-if-today-is-a-holiday)

```
Holidays::for('be')->isTodayHoliday(); // true or false
```

### Getting upcoming holidays

[](#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

[](#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

[](#getting-the-name-of-a-holiday)

```
Holidays::for('be')->getName('2024-01-01'); // 'Nieuwjaar'
```

### Determining whether a country is supported

[](#determining-whether-a-country-is-supported)

```
Holidays::has('be'); // true
Holidays::has('unknown'); // false
```

Adding a new country
--------------------

[](#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

[](#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

[](#register-your-country)

In `src/CountryRegistry.php`, add your ISO country code and country class to the `MAP` constant.

### Regional holidays

[](#regional-holidays-1)

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

[](#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 Monday
- `sundayToNextMonday(CarbonInterface $date)` — shifts Sunday to Monday
- `observedChristmasDay(CarbonInterface $date)` — Saturday to Monday, Sunday to Tuesday
- `observedBoxingDay(CarbonInterface $date)` — Saturday to Monday, Sunday to Tuesday

### Holiday types

[](#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

[](#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

[](#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

[](#testing)

1. 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();
});
```

2. Run `vendor/bin/pest --update-snapshots` to generate the snapshot.
3. Verify the generated snapshot in `tests/.pest/snapshots/` is correct.

Testing
-------

[](#testing-1)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Upgrading
---------

[](#upgrading)

Please see [UPGRADING](UPGRADING.md) for how to upgrade to a new major version.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Niels Vanpachtenbeke](https://github.com/Nielsvanpach)
- [Freek Van der Herten](https://github.com/freekmurze)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

70

—

ExcellentBetter than 100% of packages

Maintenance97

Actively maintained with recent releases

Popularity62

Solid adoption and visibility

Community35

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 62.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~19 days

Recently: every ~13 days

Total

47

Last Release

27d ago

Major Versions

0.0.2 → 1.0.02024-01-17

1.24.0 → v2.x-dev2026-02-26

v1.x-dev → 2.0.02026-04-13

PHP version history (3 changes)0.0.1PHP ^8.1

v2.x-devPHP ^8.4

v1.x-devPHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7535935?v=4)[Spatie](/maintainers/spatie)[@spatie](https://github.com/spatie)

---

Top Contributors

[![Nielsvanpach](https://avatars.githubusercontent.com/u/10651054?v=4)](https://github.com/Nielsvanpach "Nielsvanpach (420 commits)")[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (81 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (18 commits)")[![lowv-developer](https://avatars.githubusercontent.com/u/17094957?v=4)](https://github.com/lowv-developer "lowv-developer (17 commits)")[![thecaliskan](https://avatars.githubusercontent.com/u/13554944?v=4)](https://github.com/thecaliskan "thecaliskan (14 commits)")[![patressz](https://avatars.githubusercontent.com/u/81393875?v=4)](https://github.com/patressz "patressz (12 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (11 commits)")[![levrailoup](https://avatars.githubusercontent.com/u/28599391?v=4)](https://github.com/levrailoup "levrailoup (10 commits)")[![lamelas](https://avatars.githubusercontent.com/u/210068?v=4)](https://github.com/lamelas "lamelas (8 commits)")[![thinkstylestudio](https://avatars.githubusercontent.com/u/322368?v=4)](https://github.com/thinkstylestudio "thinkstylestudio (6 commits)")[![Chris53897](https://avatars.githubusercontent.com/u/7104259?v=4)](https://github.com/Chris53897 "Chris53897 (6 commits)")[![arnebr](https://avatars.githubusercontent.com/u/1068416?v=4)](https://github.com/arnebr "arnebr (6 commits)")[![davsaniuv](https://avatars.githubusercontent.com/u/58817543?v=4)](https://github.com/davsaniuv "davsaniuv (5 commits)")[![mauricius](https://avatars.githubusercontent.com/u/7000852?v=4)](https://github.com/mauricius "mauricius (5 commits)")[![xHeaven](https://avatars.githubusercontent.com/u/14284867?v=4)](https://github.com/xHeaven "xHeaven (4 commits)")[![Kenny1291](https://avatars.githubusercontent.com/u/53661492?v=4)](https://github.com/Kenny1291 "Kenny1291 (4 commits)")[![amitsamtani](https://avatars.githubusercontent.com/u/107021?v=4)](https://github.com/amitsamtani "amitsamtani (4 commits)")[![Lukasss93](https://avatars.githubusercontent.com/u/4071613?v=4)](https://github.com/Lukasss93 "Lukasss93 (3 commits)")[![calonzolg](https://avatars.githubusercontent.com/u/19369562?v=4)](https://github.com/calonzolg "calonzolg (3 commits)")[![Martin-Welte](https://avatars.githubusercontent.com/u/26961559?v=4)](https://github.com/Martin-Welte "Martin-Welte (3 commits)")

---

Tags

dateholidaysphpspatieholidays

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/spatie-holidays/health.svg)

```
[![Health](https://phpackages.com/badges/spatie-holidays/health.svg)](https://phpackages.com/packages/spatie-holidays)
```

###  Alternatives

[illuminate/support

The Illuminate Support package.

630113.0M41.5k](/packages/illuminate-support)[spatie/laravel-analytics

A Laravel package to retrieve Google Analytics data.

3.3k6.1M68](/packages/spatie-laravel-analytics)[spatie/laravel-schedule-monitor

Monitor scheduled tasks in a Laravel app

9946.5M17](/packages/spatie-laravel-schedule-monitor)[spatie/ssl-certificate

A class to easily query the properties of an ssl certificate

7515.2M39](/packages/spatie-ssl-certificate)[solspace/craft-freeform

The most flexible and user-friendly form building plugin!

54681.3k19](/packages/solspace-craft-freeform)[flarum/core

Delightfully simple forum software.

201.4M2.3k](/packages/flarum-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
