Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Us Holidays Laravel Package

geoffreyrose/us-holidays

A Laravel/PHP package for working with US holidays. Check whether a date is a holiday, retrieve holiday names and dates, and handle observed dates through a simple API for scheduling, calendars, and business-day logic.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer:

composer require geoffreyrose/us-holidays

On Laravel 5.5+ the service provider and Holidays facade alias are auto-discovered. On older versions, register GeoffreyRose\Holidays\Providers\HolidaysServiceProvider::class in config/app.php and alias 'Holidays' => GeoffreyRose\Holidays\Facades\Holidays::class.

Where to look first:

  1. README.md for the exact method signatures (they're the whole API surface).
  2. src/Holidays.php — every holiday check is a method here; the observed-date logic lives here too.
  3. config/holidays.php — this is where custom holidays go.

First use case — the one you'll actually paste on day one:

use GeoffreyRose\Holidays\Facades\Holidays;

Holidays::isHoliday('2025-12-25');            // true
Holidays::isHoliday('2025-12-25', 'Christmas'); // true (named check)
Holidays::getHolidayName('2025-12-25');       // "Christmas Day"

The typical first integration is a "is this a business day?" check for SLA/payroll/queue timing, which you combine with isWeekend() or Carbon's isWeekend() in your own helper.

Implementation Patterns

Business-day calculators. The package gives you the holiday half of the problem; you provide the weekend half:

public function isBusinessDay(Carbon $date): bool
{
    return !$date->isWeekend() && !Holidays::isHoliday($date);
}

Keep that helper in a single service class so the rest of the app doesn't know about the package — makes mock/stubs and later swaps trivial.

Named holiday checks over date math. Don't hardcode '2025-11-27' for Thanksgiving. Use the named check and let the package resolve the floating holiday (4th Thursday of November) and observed dates:

if (Holidays::isHoliday($date, 'Thanksgiving Day')) { /* ... */ }

Observed vs. actual dates. Most US federal holidays shift when they fall on a weekend (e.g. Christmas Saturday → observed Friday). The package exposes both via named checks and an isObservedHoliday()-style method — pick the one that matches your business meaning:

  • Payroll / bank settlement → observed date.
  • Calendar display / commemoration → actual date.

If both matter, check isHoliday() (actual) AND isObservedHoliday() and branch explicitly. This is the single most common source of "why did the scheduler fire on Saturday" bugs.

Calendar / admin UIs. For populating a month view or year plan, iterate Carbon days and ask the package:

$holidays = collect(CarbonPeriod::create('2025-01-01', '2025-12-31'))
    ->filter(fn ($d) => Holidays::isHoliday($d))
    ->map(fn ($d) => ['date' => $d->toDateString(), 'name' => Holidays::getHolidayName($d)]);

Cache the result per year — it's cheap but called per-day and you'll notice it on a large grid.

Custom holidays. Add company-specific days (shutdown, floating PTO) via the published config or the add-custom-holiday method documented in the README:

php artisan vendor:publish --tag=holidays-config

Then register them in config/holidays.php. Keep the list in config, not in code, so ops can adjust without a deploy.

Scheduled jobs and commands. Wrap the holiday check into a trait or base command so $this->shouldRunToday() is one call — otherwise every command grows its own check and they drift.

Validation. A rule like "must be a business day" reads well:

Rule::when(fn ($attr, $val) => Holidays::isHoliday($val), fn () => 'date not allowed: holiday');

Gotchas and Tips

Carbon 2 vs. Carbon 3. This package pins to a Carbon version. If your app is on Carbon 3 (Laravel 11+ default) and the package isn't yet, you'll get either an install conflict or subtle CarbonImmutable/type errors. Check composer.lock for the resolved Carbon major before debugging behavior. If you need CarbonImmutable, don't assume it works — test that Holidays::isHoliday($immutable) behaves identically.

Saturday vs. Sunday observance. The observed-date rules differ: Saturday holidays shift back to Friday, Sunday holidays shift forward to Monday. A single "if weekend then Monday" assumption is wrong half the time. Rely on the package's observed logic; don't reimplement.

Floating holidays aren't constants. Thanksgiving, MLK, Memorial Day, Presidents' Day, Labor Day, Columbus Day — these move every year. If you cache a "holiday map" keyed by year, invalidate per year, not per deploy.

Timezones. The package works on dates, not datetimes. Passing a Carbon with a time component is fine, but if you're checking "is today a holiday" in a multi-timezone app, normalize to the user's or the business's timezone first — Holidays::isHoliday(now()) in UTC is not "today" for a user in Hawaii.

Named checks are exact-string-sensitive. 'Christmas' vs 'Christmas Day' matters. Pull names from getHolidayName() in your tests, or assert with the actual resolved list, so renames in a package update surface as failures.

Not all 42 holidays are federal. The package covers far more than the 11 federal holidays. If you're modeling federal-only logic (bank settlement, IRS deadlines), use the federal-specific checks or maintain an allow-list of names — otherwise "is a holiday" will over-trigger on things like Valentine's Day or Halloween.

Package freshness. Last release is 2025-07-29 and the repo sits at ~62 stars — small, but the maintainer is active. Treat new releases like any low-traffic dependency: pin the minor, read the changelog, and have a test that asserts a known date resolves correctly (e.g., 2025-07-04 → Independence Day) so a regressions shows up immediately.

Escaping through the facade. If you mock the facade in tests (Holidays::shouldReceive(...)), remember it's a real facade — forgetting Holidays::clearResolvedInstances() between tests leaks state. Prefer injecting a small HolidayService wrapper you control if you test holiday logic heavily.

Caching extension point. If the package doesn't expose a cached "all holidays for year" call, build one yourself and memoize on a static or a scoped binding. Repeated per-day calls in a loop are the usual performance complaint, and it's trivially fixable on your side.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator