Product Decisions This Supports
- Build vs. buy for "opening hours" logic. Any feature asking "are we open right now?", "when do we next open?", or "show this week's hours" is commodity logic with a surprising number of edge cases (overnight ranges past midnight, recurring holidays, DST, overlapping ranges, per-date exceptions). This package turns a multi-week build into a
composer require plus a thin adapter.
- Feature scoping for hours-dependent work. Concretely unblocks: store/location pages with a live open/closed badge, "next open at…" messaging, click-and-collect and order-ahead windows, delivery/ETA promises, support live-chat and IVR routing, and SLA/business-hours clock calculations.
- Roadmap sequencing. Because it is stateless and config-driven, it can ship as an internal service behind a feature flag in days rather than being scheduled as a platform initiative. That lets hours-dependent features move up the roadmap without a calendar-infrastructure dependency.
- Data-model and ownership decision. Hours can live in config, JSON, or DB — the package doesn't care. This forces an explicit PM decision: who owns schedule editing (admin UI, CSV import, ops runbook), and whether schedules are versioned/audited. The package provides none of that, so budget it separately.
- Timezone product decision. The
timezone.input / timezone.output options force the question "do we display hours in the customer's local time or the venue's local time?" — a user-facing decision that is cheap to make now and expensive to retrofit.
- Boundary-setting. It deliberately does not model capacity, slots, staff, or resource booking. Adopting it clarifies that a real booking engine is a separate (and larger) roadmap item, not something this dependency will grow into.
When to Consider This Package
Good fit when:
- The stack is PHP/Laravel (it is framework-agnostic — no service provider, config publishing, or Eloquent casting — so it drops in cleanly but gives you no Laravel-specific conveniences).
- Hours are a supporting capability, not the product: a weekly recurring schedule plus date-based and recurring exceptions covers ~90% of real-world storefronts.
- You need the primitives, not just rendering:
isOpenAt, nextOpen/nextClose, currentOpenRange, previousClose, plus forWeek/forWeekCombined/forWeekConsecutiveDays for display.
- You want a small, MIT-licensed, tested dependency (build, coverage, and quality badges are present; README, changelog, and releases are maintained) rather than owning schedule logic.
- Overnight businesses matter — the
overflow flag handles the nightclub/restaurant "open till 3am" case that naive implementations get wrong.
Look elsewhere / plan to build more when:
- Booking, capacity, or staff-level scheduling is core. This is a rules engine, not a booking engine.
- You need "find all locations open now" at scale. The object is in-memory with no query/index story; you'll need to persist derived open-state or evaluate a DB-side approach.
- Rule complexity is high. The README explicitly warns that filters are evaluated per-date with no caching — heavy or numerous closures will hurt. Model the cost before committing.
- You need an admin UI, schedule versioning, audit trails, or approval workflows for hours changes. All of that is yours to build.
- The logic must be shared with non-PHP clients or services — you'd want a written spec, not a package.
- Signals warrant caution: the dependent count in our data (0) doesn't reflect real ecosystem usage but does mean you can't lean on "everyone else uses it" as validation; do a short internal spike and pin a version. Confirm the release cadence and BC policy before locking in (the latest release date looks anomalously future-dated, so verify it against Packagist directly).
How to Pitch It (Stakeholders)
For executives: This is commodity plumbing for "when are we open," and it's the kind of thing teams routinely underestimate and rebuild badly. It's free (MIT), maintained by Spatie — a well-known, long-standing PHP agency — and removes the classic failure modes: holiday closures, overnight hours, timezone drift, and "next open" math. Adopting it shortens time-to-market on any hours-dependent feature from weeks to days, and because the surface area is small and the license permissive, the downside risk is negligible — we can wrap it and replace it if needed.
For engineering: composer require spatie/opening-hours. Immutable value objects (Time, TimeRange, OpeningHoursForDay), explicit exceptions on overlapping ranges with a mergeOverlappingRanges escape hatch, input/output timezone conversion, and Carbon integration via cmixin/business-time. Tests, coverage, and static-quality tooling are in place. Two asks: (1) wrap it behind our own domain service so we're not importing Spatie\OpeningHours across the codebase, and (2) treat filter-based schedules as a performance-sensitive path — cache or precompute where they appear in hot requests.
Ask: Approve as a dependency for the next hours-dependent feature, with a one-to-two-day integration spike and a decision checkpoint on where schedule data and editing live.