Opening Hours
A store opens 09 00-18 00 on weekdays and 10 00-14 00 on Saturday. A doctor's office closes for two weeks in August. A restaurant takes a lunch break from 14:00 to 18:00. The shape connectors and editors return for all of these is the same OpeningHours record: a weekly schedule keyed by ISO weekday, an optional IANA timezone the wall-clock times are interpreted in, and an optional map of date-specific exceptions for closures and one-off openings.
import type { OpeningHours } from '@laioutr-core/core-types/common';
interface OpeningHours {
timeZone?: string;
schedule: Partial<Record<Weekday, OpeningWindow[]>>;
exceptions?: Record<string, OpeningWindow[]>;
}
The type follows the shape of schema.org/OpeningHoursSpecification without forcing the verbose Schema.org structure on connectors. It is consumed by the ui-kit OpeningStatus, OpeningStatusIndicator, OpeningStatusDetail, and OpeningHoursWeeklyTable components, and by the LocationCard block.
Fields
timeZone
An optional IANA timezone identifier (e.g. 'Europe/Berlin', 'America/New_York'). The wall-clock HH:mm times inside schedule and exceptions are interpreted in this zone. When omitted, the browser's local zone is used, which is rarely what you want for a multi-location store.
Always return the location's local timezone from connectors. A London shopper looking at a Paris store should still see Paris's opening times in Paris's wall-clock hours, not their own offset.
schedule
The weekly schedule, keyed by ISO weekday (1 = Monday, 7 = Sunday). Each value is an array of OpeningWindow records that describe when the location is open that day. A missing key (or an empty array) means closed that day.
A typical "Monday to Friday, plus Saturday morning" schedule:
const schedule: OpeningHours['schedule'] = {
1: [{ start: '09:00', end: '18:00' }],
2: [{ start: '09:00', end: '18:00' }],
3: [{ start: '09:00', end: '18:00' }],
4: [{ start: '09:00', end: '18:00' }],
5: [{ start: '09:00', end: '20:00' }],
6: [{ start: '10:00', end: '14:00' }],
// 7 omitted: closed Sundays
};
A day with multiple windows (e.g. a lunch break) carries two entries:
const tuesday: OpeningWindow[] = [
{ start: '09:00', end: '13:00' },
{ start: '14:30', end: '19:00' },
];
exceptions
An optional map of date-specific overrides, keyed by 'YYYY-MM-DD'. The date is interpreted in the schedule's timeZone. Use this for holidays, special hours, and one-off closures. An empty array means closed that day.
const exceptions: OpeningHours['exceptions'] = {
'2026-12-24': [{ start: '09:00', end: '14:00' }], // Christmas Eve, short day
'2026-12-25': [], // Christmas Day, closed
'2026-12-26': [], // Boxing Day, closed
};
When a date appears in exceptions, it overrides the weekly schedule for that day completely. The components do not merge weekly windows with exception windows.
Related types
Weekday
type Weekday = 1 | 2 | 3 | 4 | 5 | 6 | 7;
ISO 8601 weekday, with 1 for Monday and 7 for Sunday. Storing days as numeric ISO weekdays keeps the type stable across locales and avoids the Sunday-vs-Monday "is day 0 the first day of the week?" trap.
OpeningWindow
interface OpeningWindow {
start: string; // 'HH:mm'
end: string; // 'HH:mm'
}
A single open window expressed as wall-clock times in the parent schedule's timezone. Both start and end are 24-hour 'HH:mm' strings.
Overnight windows (where end is earlier than start, e.g. a bar that closes at 02:00) are not supported and are treated as same-day by the useOpeningStatus composable.
Consuming the data
The ui-kit ships a useOpeningStatus composable that turns an OpeningHours value into a reactive isOpen flag and the next state-change event:
import { useOpeningStatus } from '#imports';
import type { OpeningHours } from '@laioutr-core/core-types/common';
const openingHours: OpeningHours = {
timeZone: 'Europe/Berlin',
schedule: { 1: [{ start: '09:00', end: '18:00' }] },
};
const { isOpen, nextEvent } = useOpeningStatus(() => openingHours);
nextEvent is one of:
closes-atwhen currently open. Carries the closingtimeand a sortableinstant.opens-todaywhen closed and the next opening is later the same calendar day.opens-tomorrowwhen closed and the next opening is the next calendar day.opens-on-weekdaywhen closed and the next opening is within the next 7 days.opens-on-datewhen closed and the next opening is more than 7 days out (within a 30-day horizon).
For an empty schedule or a 24/7 schedule with no upcoming state change, nextEvent is undefined.
The composable looks ahead a maximum of 30 days. If a closure runs longer than that (e.g. a seasonal location), nextEvent returns undefined and consumers should fall back to a "Closed for the season" message rather than a relative date.
For connector authors
Return the location's local timezone, the weekly schedule, and any one-off exceptions:
import type { OpeningHours } from '@laioutr-core/core-types/common';
const munichStore: OpeningHours = {
timeZone: 'Europe/Berlin',
schedule: {
1: [{ start: '09:00', end: '20:00' }],
2: [{ start: '09:00', end: '20:00' }],
3: [{ start: '09:00', end: '20:00' }],
4: [{ start: '09:00', end: '20:00' }],
5: [{ start: '09:00', end: '20:00' }],
6: [{ start: '09:00', end: '18:00' }],
},
exceptions: {
'2026-12-24': [{ start: '09:00', end: '14:00' }],
'2026-12-25': [],
'2026-12-26': [],
'2026-01-01': [],
},
};
Three common pitfalls to avoid:
- Returning times in UTC. The schedule's
HH:mmvalues are wall-clock times in the namedtimeZone, not UTC offsets. A Berlin store opens at09:00in'Europe/Berlin', regardless of summer time. The composable resolves the right UTC instant per calendar day. - Omitting
timeZone. WhentimeZoneis missing, the components fall back to the browser's local zone. This is correct only if your storefront serves a single timezone; for multi-location stores it shows wrong times to shoppers in other regions. - Encoding closures as empty
schedulekeys. Useschedulefor the repeating pattern andexceptionsfor one-offs.
Related
OpeningStatus: the open/closed summary that consumes this type.OpeningHoursWeeklyTable: the full weekly schedule renderer.LocationCard: the location card that composesOpeningStatusfrom this type.- Schema.org
OpeningHoursSpecification: the structured-data counterpart, useful when emitting JSON-LD for SEO.