Business Opening Hours Data: Weekly Schedules and Exceptions
Normalize public schedules without turning missing hours into closures; preserve timezone, overnight intervals and dated exceptions.
KAIROXO

Business opening hours data describes a schedule reported by a source, not a guarantee that a door is open right now. A listing can omit a day, show split service periods, change for a holiday or keep separate hours for different services. Treating those values as one free-text string makes location comparisons and “open now” calculations fragile.
This workflow uses public business schedules as an example of structured web data. It does not require contact enrichment or personal details. KAIROXO provides an access or collection entry point; schedule interpretation, timezone logic and source reconciliation are application responsibilities.
Preserve source meaning before normalization
Store the displayed schedule, source URL, source business identifier and collection time before interpreting the hours. A blank field should remain missing. A closed interval should mean that the source explicitly says the business is closed for that period. “Temporarily closed” and “permanently closed” are business-status claims and should not silently replace a weekly schedule.
Identify what the hours refer to. A shop can have one schedule for collection, another for delivery and another for customer support. A restaurant may publish kitchen hours separately from seating hours. If the source does not specify the service, preserve that uncertainty rather than comparing it as if it were the same offering everywhere.

Model weekly intervals and overnight closing
Represent a day with zero or more intervals, while keeping a separate flag for unknown data. This distinguishes an explicitly closed day from a day that was not collected. Split hours become two intervals. For overnight service, identify whether the closing time belongs to the following day rather than sorting two clock strings and assuming the earlier one comes first.
{ "businessKey": "example-cafe", "timezone": "Asia/Ho_Chi_Minh", "scheduleStatus": "reported", "weekly": [ {"day": "Monday", "opens": "22:00", "closes": "02:00", "endsNextDay": true} ], "service": "unspecified", "observedAt": "2026-10-28T02:00:00Z"}This is an illustrative application record, not schema.org syntax or a real business listing. A production schema should define how it encodes all-day operation, interval overlap and missing weekdays before import begins.
Keep timezone and date exceptions explicit
Weekly opening times are local civil times. Converting them into UTC without a date can be incorrect in locations that change daylight-saving rules. Store an IANA timezone when it is known, along with the evidence used to select it. A country alone may not be enough to choose a timezone.
Apply dated exceptions separately from the normal week. A specific closed date or special opening interval can override the weekly pattern for that date. Do not overwrite the recurring schedule with a holiday observation and then carry the exception into future weeks. If two sources disagree, retain their source-specific values and collection times until a reconciliation rule or review resolves the difference.
Validate meaning, not just clock syntax
Check that day names, times and timezone identifiers are recognized, but also test whether the record's interpretation is coherent. Flag overlapping intervals, impossible date ranges, unrecognized all-day labels and duplicate records with conflicting service scope. A parser that successfully reads “9–5” has not established whether the source means morning to afternoon, evening service or a locale-specific display convention.
Make “open now” a derived result with a calculation time and rule version. If schedule data, timezone or date exceptions are missing, return unknown rather than false. Where the answer matters operationally, encourage confirmation from the business's official channel; a public listing can be stale even after a successful request.
Refresh without turning access failures into closures
Track retrieval success separately from schedule changes. An unavailable page does not show that the business closed. Compare schedules only after source identity and service scope match, and keep a change history for later inspection. A routine refresh should not replace a known schedule with an empty object simply because extraction failed.
Local fixtures should include split hours, overnight service, explicitly closed days, missing weekdays, special dates and conflicting sources. Test in a timezone with seasonal clock changes as well as one without them. The goal is to prove that the application preserves uncertainty and exceptions, not to claim perfect real-time knowledge of physical locations.