phil / opening-hours
Opening hours for PHP: weekly hours with ranges past midnight, special days and periods, whether a place is open and when it next opens in its time zone, a text form people type, and schema.org OpeningHoursSpecification
Package info
github.com/parler-haut-interagir-librement/opening-hours
pkg:composer/phil/opening-hours
Requires
- php: >=8.5
- ext-mbstring: *
Requires (Dev)
- phpunit/phpunit: ^13.4
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-11 13:32:02 UTC
README
A place's opening hours, and whether it is open right now.
phil/opening-hours holds a place's hours as value objects. A week has its hours, with ranges that may close past
midnight. Special hours replace them for a day or a period, such as a holiday when the place is closed or a summer
with other hours. The library says whether the place is open at a moment and when it next opens, in the place's time
zone. It groups the week in runs of days with the same hours, reads and writes a text form people type, gives
schema.org's openingHoursSpecification, and turns hours into an array of texts for one JSON column. It does not
name days or write times in a language, which phil/opening-hours-bundle does with ICU. It holds no public holidays
either: special hours are the place's own.
It is for any application that lists places people visit: a shop, a library, a club, a venue. A visitor wants to know whether the door is open now, and a search engine wants the hours in a form it reads.
It is a plain PHP library, usable in any PHP code, with no dependency beyond ext-mbstring. In a Symfony
application, reach for phil/opening-hours-bundle, which adds a form, a Doctrine column type and Twig functions.
The design rests on small immutable types: TimeOfDay, TimeRange, DayHours, SpecialHours and OpeningHours.
A moment is turned to the place's time zone before it is read, so asking at 14:30 UTC in January about a shop in
Toronto asks about 09:30 there.
Status
| Part | State |
|---|---|
TimeOfDay, TimeRange, DayHours, SpecialHours, OpeningHours |
Implemented and tested |
isOpenAt(), nextOpening(), groups() |
Implemented and tested |
HoursText, OpeningHoursSchema, OpeningHoursArray |
Implemented and tested |
Documentation
| Document | What it covers |
|---|---|
| Installation | Requirements and installing. |
| Hours | Times, ranges, days, special hours, and the time zone. |
| Asking | Open now, next opening, the hours of a day, the week in runs. |
| Text, schema.org and storage | The text form, the schema.org specifications, the array. |
| Extension points | The ports, arguments and data an application chooses or replaces. |
| Testing | The library's tests and mutation bar. |
| Reference | Every type of the library, with its role. |
Quick start
composer require phil/opening-hours
use Phil\OpeningHours\HoursText; use Phil\OpeningHours\OpeningHours; $weekday = HoursText::day('09:00-12:00, 13:00-17:00'); $hours = OpeningHours::of( [1 => $weekday, 2 => $weekday, 3 => $weekday, 4 => $weekday, 5 => HoursText::day('09:00-17:00, 20:00-02:00')], HoursText::specials("2026-12-25 # Christmas"), 'America/Toronto', ); $hours->isOpenAt(new DateTimeImmutable()); // true or false $hours->nextOpening(new DateTimeImmutable()); // the next opening, in Toronto
Requirements
PHP 8.5 or later with ext-mbstring.
Contributing
Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.
License
MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.