Time zones
By default the scheduler shows times in the viewer’s own zone. Pass timeZone to show them in another one: a head office, a room in another city, the zone of whoever is booking.
<ResourceScheduler resources={resources} timeZone="America/New_York" businessHours={{ startHour: 9, endHour: 17 }} onEventDrop={(event, from, to, start, end) => save(event.id, start, end)}/>timeZone takes an IANA name (Europe/Paris, America/New_York, Asia/Kolkata). Leave it out and nothing changes. A name the browser does not know warns in the console and falls back to the viewer’s zone.
What changes
Section titled “What changes”- Events are instants, as a
Datealways is. An event at 08:00 UTC is drawn at 09:00 in London in summer and at 17:00 in Tokyo, on the day it falls on there. - Business hours are hours in the zone:
businessHours={{ startHour: 9, endHour: 17 }}shades everything outside 9 to 17 on the clock of that zone. - Today, the now line and the Today button follow the zone.
unavailableranges are instants, like events.- Recurring events repeat at the same wall-clock time in the zone, also across its clock changes, so a 09:00 standup stays at 09:00 when summer time starts.
What you receive
Section titled “What you receive”Handlers give you instants, ready to store: onEventDrop, onEventResize, onEventCreate, onSlotSelect, onEventClick, onDateChange, onRangeChange, the arguments of isValidDrop and eventOverlap, and what the ref methods take and return (goTo, scrollToTime, getVisibleRange). Drop an event on 14:00 in the grid and onEventDrop hands you the moment that is 14:00 in the zone.
Render props (renderEventPopover, renderDateHeader, renderEmptyCell, renderTimeSlot, renderResourceHeader) receive dates as wall-clock Dates in the zone: format(event.startDate, "p") shows the zone’s time, which is what you want when drawing. To show a stored instant in the zone yourself, use utcToZoned; zonedToUtc goes the other way.
import { format } from "date-fns";import { utcToZoned, zonedToUtc } from "resource-scheduler";
format(utcToZoned(event.startDate, "Asia/Tokyo"), "p"); // "5:00 PM" wherever the browser iszonedToUtc(new Date(2026, 9, 7, 9), "Asia/Tokyo"); // the instant it is 09:00 on 7 Oct in TokyoExport is unaffected: eventsToICS writes the instants, and icsToEvents reads TZID zones into instants.
Recurring events
Section titled “Recurring events”A series is stored like any event: the instants of its first occurrence plus a recurrence. With timeZone it repeats at the same wall-clock time in the zone, also across a clock change in that zone: a daily 09:00 in Paris is 07:00 UTC until 25 October 2026 and 08:00 UTC from then on, “the last Friday at noon” in New York is 16:00 UTC on 30 October and 17:00 UTC on 27 November, and a series every 4 hours from midnight is 00:00, 04:00, 08:00 … on every day, also on a day with 23 or 25 hours. It is the same whatever zone the viewer’s machine is in. Handlers receive the occurrence’s instants as usual.
untilandexceptionsare calendar days, read as days in the zone (build them withnew Date(y, m, d)).- One zone per scheduler: a series with a zone of its own, different from
timeZone, is not supported. - A reading that does not exist in the zone (02:30 when its clocks go forward) is shown at that reading and reported with the offset from before the change, as for any event. An hourly series skips it.
Limits
Section titled “Limits”- A day on the grid has 24 hours. On the day a zone changes its clock, the hour that does not exist is still drawn, and the hour that happens twice is drawn once. A time that does not exist (02:30 when clocks go forward at 02:00) is stored as the moment an hour later, and one that happens twice as the first of the two, as RFC 5545 says.
- The viewer’s machine cannot show a wall-clock time its own zone skips. Because the grid works on wall-clock
Dates, a time that does not exist in the browser’s zone (02:30 on the night its clocks go forward) appears an hour later. This only matters when the browser’s zone andtimeZonechange their clocks on different days and an event sits in that hour. - Recurrence
untilandexceptionsare calendar days, not instants, and are never converted:exceptions: [new Date(2026, 9, 14)]means 14 October, in whichever zone you show. weekStartsOn,localeandhour12are unchanged;timeZoneonly moves the clock.- Changing
timeZonewhile the scheduler is on screen keeps the calendar day you were looking at, not the instant.