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.
Architecture fit. geoffreyrose/us-holidays is a thin, single-purpose library: it extends nesbot/carbon with US holiday awareness and exposes a Laravel facade plus a mechanism for registering custom holidays. That is a narrow, well-bounded responsibility, which is exactly the profile a TPM wants for a calendar dependency — it does not own scheduling, persistence, or timezone storage, so it composes cleanly into existing date logic rather than competing with it. It is most valuable in domains doing business-day arithmetic: billing and invoicing cycles, SLA and due-date calculation, payroll cutoffs, eligibility windows, and notification suppression ("don't page on Thanksgiving"). The published count of 42 holidays is a signal to interrogate, not a feature to celebrate: a set that large almost certainly mixes federal legal holidays (New Year's, Juneteenth, Thanksgiving) with cultural observances (Valentine's, Halloween, Easter). Consumers must be able to select the subset that matches their business definition, because a "holiday" for a retail calendar is not the same as a "holiday" for a bank or a federal contractor.
Integration feasibility. Low. It is Composer-installable, supports Laravel package auto-discovery for the service provider and facade alias, and requires no database, queue, or external service. A competent Laravel engineer can have it working in an afternoon and behind tests in a day. The real work is not installation; it is defining, in writing, which holidays your product actually honors and how "observed" shifting works.
Technical risk. Four items dominate:
composer update on Carbon is the most likely way this breaks in production.Key questions before approval. Which specific holidays are in the 42, and is observed-date shifting configurable? Does it expose a "business day" primitive or only isHoliday-style predicates? How are custom holidays registered — per-request, config file, or runtime? What is the timezone semantics of "is today a holiday" — server-local, app-configured, or caller-supplied? Which PHP and Carbon majors are supported in the 2025-07-29 release, and is there CI covering the Laravel versions we run? What is the test coverage on observed-date edge cases?
Stack fit. Direct fit for Laravel 9–12 on PHP 8.1+ with Carbon 2 or 3, provided the compatibility matrix checks out; usable standalone in any Composer project via Carbon alone, which keeps the facade from becoming a lock-in vector. Do not adopt it for non-US locales — the name is the contract.
Migration path. Most teams reaching for this are currently maintaining a hardcoded array of holiday dates or a switch on month/day scattered across services. Sequence the migration as: (1) spike the package in a branch and enumerate the holidays it returns for the next three years; (2) diff that against the existing hardcoded list and get a human to sign off on every discrepancy; (3) introduce an internal interface — e.g. BusinessCalendar with isBusinessDay(), nextBusinessDay(), addBusinessDays() — and implement it over this package; (4) migrate call sites to the interface, not the facade. Step 3 is the one that matters: it converts a 62-star dependency into a swappable detail and lets you patch a holiday rule yourself without forking.
Compatibility. Pin the package and Carbon to explicit majors in composer.json; treat Carbon upgrades as a deliberate change with a regression run, not a routine bump. Under Laravel 11/12's slim skeleton, verify auto-discovery registers the facade alias as expected, and prefer constructor/container injection over the static facade in application code so tests can substitute a fake calendar.
Sequencing. Ship behind one low-risk consumer first — display logic or a notification-suppression check — where a wrong answer is visible and cheap. Move billing, SLA, or payroll logic onto the interface only after the holiday-set sign-off and after you have your own tests covering weekend observance, the New Year's prior-year shift, and a custom holiday. Budget roughly 1–3 engineer-days end to end, most of it in reconciliation and test-writing rather than integration.
Maintenance. Near-zero steady-state cost: no daemons, no migrations, no storage. The ongoing obligation is a quarterly check of the upstream repo and an annual review of the holiday list — rules change by legislation and executive order, and an unmaintained upstream means you absorb that work. Because the code is MIT and small, the credible fallback is a vendored fork if the maintainer disappears; document that contingency rather than leaving it implicit.
Support. No commercial support and no SLA. Resolution for defects is "open an issue and wait," which is tolerable for a computation-only library and intolerable for anything a customer contract depends on. The wrapper interface is the mitigation: worst case you replace the implementation in one file.
Scaling. Effectively free. Holiday resolution is in-memory arithmetic; it will not be your bottleneck. The only scaling consideration is call volume in tight loops — computing the same year's holiday set repeatedly across thousands of records — so memoize the resolved calendar per year per request/job, and precompute in batch processes.
Failure modes. Ranked by impact: silently wrong observed dates flowing into money or commitments; Carbon major-version drift breaking the package after a routine composer update; timezone mismatch producing off-by-one-day answers for users near midnight or for a UTC-configured server serving US users; and coverage gaps (state holidays, market closures, bank holidays) that no one notices until a specific customer escalates. Every one of these is caught by a small owned test suite — treat that suite as part of the integration cost, not as optional hardening.
Ramp-up. Hours. The API surface is small, the concepts are familiar to any PHP developer, and the only real learning is your organization's definition of a business day. The documentation burden is correspondingly small; the durable artifact to write is a one-page internal note stating which holidays the product honors, how observance is handled, and who owns the annual review.
Verdict for planning purposes. Approve as a convenience dependency behind an abstraction for US-only business-day logic, with pinned versions, owned edge-case tests, and a named owner for the annual holiday review. Reject as the system of record for contractual calendars that require state, banking, or exchange-specific rules.
How can I help you explore Laravel packages today?