Skip to content
Neos Meet is in public beta.3 months of any paid plan free for every beta user — and permanent perks for the first 100.See the beta terms

How it works

Timezone handling in scheduling: why cross-timezone bookings go wrong

Wall clock vs instant, DST transitions that delete and duplicate an hour, midnight rollover, and half-hour offsets. The five places a booking's time goes wrong.

· 8 min read

Almost every scheduling bug that reaches a customer is a timezone bug, and they all rhyme: someone publishes 9-to-5, an invitee in another country sees 6 AM slots, and a meeting that was supposed to be Tuesday afternoon shows up Tuesday morning — or Monday night.

These aren't exotic edge cases. They come from one conceptual confusion that is easy to make and hard to see, plus four places it can surface. This post is the field guide: what goes wrong, why, and what to check on your own booking page today.

The one idea: wall clock is not an instant

There are two different kinds of time in a scheduler, and everything depends on keeping them apart.

Wall clockInstant
What it is“Tuesday at 9:00 AM” — a label a human reads off a clockA single point in time, the same for everyone on Earth
Example9:00, Tuesday, America/Los_Angeles2026-09-15T16:00:00Z
Used forYour working hours, date overrides, “no meetings before 10”Bookings, calendar busy blocks, reminders
Needs a timezone to mean anything?Yes — and the timezone can change what instant it maps toNo — it already is one
Every timezone bug is a wall clock treated as an instant, or the reverse.

Your availability is wall clock: you mean 9 AM where you are, forever, no matter what daylight saving does to the offset. A booking is an instant: one moment that both parties attend, which each of them then reads on their own clock. The scheduler's job is the conversion between them, and it has to happen in exactly one place with the host's timezone attached — every time.

The rule

Store working hours as wall clock plus a named timezone (America/Los_Angeles, never a UTC offset like -08:00). Store bookings as instants. Convert only at the boundary between them. Offsets are a property of a zone at a moment — hard-coding one bakes in whichever side of DST you happened to be on.

Where it actually goes wrong

1. The server's timezone leaks in

The most common production bug, and the most invisible in development: code that asks a date “what weekday are you?” or “what's your date?” without saying in which zone. It answers in whatever zone the machine is set to. On a laptop in California that's the host's zone and everything looks perfect; on a server running UTC, every host west of Greenwich gets their Monday rules applied to Sunday evening.

This is why a scheduling bug can pass every local test and appear only after deploy. The fix is discipline: no date operation in the engine is allowed to use the ambient zone, and the weekday of a calendar date is computed as a pure calendar property rather than read off a local clock.

2. Daylight saving, twice a year, in two different ways

DST breaks scheduling in two distinct ways, and most implementations only handle one.

  • Spring forward: an hour that doesn't exist. When clocks jump from 1:59 to 3:00, the local time 2:30 never occurs. A rule that offers a 2:30 slot has to resolve to something, and if the conversion silently picks the wrong side, every slot after it shifts by an hour.
  • Fall back: an hour that happens twice.1:30 AM occurs once on daylight time and again an hour later on standard time. “1:30” is genuinely ambiguous, so the system must pick one deterministically — and pick the same one on the booking page, in the confirmation email, and in the calendar invite.
  • And the invariant that matters more than either:a 9-to-5 rule must still read as 9-to-5 on both sides of a transition. The underlying UTC offset changes; the host's experience must not.

That last one is the property worth testing, because it's the one users notice. Our availability engine has a test suite for exactly this: spring-forward and fall-back days in both northern and southern hemisphere zones (the southern transitions run the opposite direction, in the opposite months, which catches assumptions no US-only test will), plus date overrides landing on a transition day.

3. Midnight, and the 24:00 problem

“Available until midnight” is an ordinary thing to want and a classic way to get zero slots. Midnight-ending is the wall-clock time 24:00 — which, treated naively, wraps back to 00:00 of the same day, making the window run from 6 PM to midnight that morning: a window of negative length, so nothing renders. The window has to roll into the next calendar day.

There's a companion bug: an evening slot in a western timezone is already tomorrow in UTC. A 9 PM Tuesday booking in Los Angeles is Wednesday 04:00 UTC. If the page groups slots by the UTC date, that slot appears under Wednesday and the host's Tuesday evening looks empty. Grouping must happen in the host's zone.

4. Not every offset is a whole hour

India is UTC+5:30. Nepal is +5:45. Parts of Australia are +9:30, and the Chatham Islands are +12:45 — with a DST transition on top. Any arithmetic that assumes whole-hour offsets produces slots at :30 past for half the world, or silently rounds people out of their own working hours. We test half-hour and 45-minute zones deliberately for this reason.

5. The invitee's browser guesses

The booking page reads the invitee's timezone from their browser. That is usually right and occasionally very wrong: a laptop that hasn't updated after a flight, a VPN or virtual desktop reporting the datacentre's zone, a corporate image pinned to headquarters. This is why a booking page must always displaythe timezone it's showing times in, and let the invitee change it. A page that shows bare times is asking someone to miss a meeting.

Why teams make it harder

Everything above applies to one host. Pool several and the compounding starts: each host has their own zone and their own hours, and a shared link has to merge them into one grid for an invitee in a fourth zone. Get any host's conversion wrong and the error is invisible — the link just shows a slightly odd set of times, and someone eventually gets a 7 AM call.

The structural fix is that each host's availability is computed entirely in their own zone, as instants, before anything is merged. Merging sets of instants is timezone-free; the result is converted once, at the very end, for display. If you're evaluating a tool for a distributed team, that is the property to probe — see how pooled assignment works for the rest of that picture, and team schedulingfor how it's set up here.

A ten-minute audit of your own booking page

  1. Check the timezone label on your availability settings.Not the times — the zone. If it says something you didn't choose, it was guessed from a browser, possibly on a trip.
  2. Open your public booking page in a private windowand confirm the times match the hours you published, and that the page names the timezone it's displaying.
  3. Switch the page's timezone selector to somewhere far away — Tokyo, Berlin — and check the same slot moves by the right number of hours, not by one extra or one fewer.
  4. Look at a date after the next DST changein your zone. Your morning slots should still start at the same local hour. If they've moved by an hour, stop and report it.
  5. If you work evenings, check the last slot of the day and that the day after it still has slots. Midnight-boundary bugs show up right here.
  6. Book one real meeting and open the calendar invite.The invite is the artifact that matters — if the page and the invite disagree, trust neither until it's fixed.
  7. For a team link, have a host in another zone do steps 1 and 2 on their own settings. Their hours are computed in their zone, and only they can spot a wrong label.

If you're building one

  • Named zones only. Never store or transmit a fixed offset for a recurring rule.
  • One function converts wall clock plus zone to an instant. Everything else calls it. Every timezone property of the system then becomes a property of that one function — which makes it testable.
  • Test the transitions, both directions, in both hemispheres, plus a non-whole-hour zone.
  • Test the day boundary: minute 1440, and evening slots whose UTC date is tomorrow.
  • Set the CI timezone to something that isn't UTC. A suite that only ever runs at UTC cannot catch an ambient-zone leak.
  • When a host's calendar can't be checked, offer nothing rather than guessing. Fewer slots is a nuisance; a double-booking is a broken promise.

Frequently asked

Why does my booking page show the wrong times?

Usually the availability schedule is saved in a different timezone than you think — often one guessed from a browser while travelling. Check the timezone label on your availability settings first, then open your public page in a private window and confirm it names the zone it's displaying times in.

What happens to my availability when daylight saving changes?

Nothing should change from your point of view: hours are stored as wall-clock times in a named timezone, so 9 AM stays 9 AM across the transition even though the underlying UTC offset shifts. Invitees in zones that change on a different date (or not at all) will see the gap between you move by an hour for a couple of weeks — that's correct, not a bug.

Which timezone does the invitee see?

The one their browser reports, with a selector to change it. Browsers are usually right and occasionally wrong — VPNs, virtual desktops, and laptops that haven't caught up after a flight all misreport — which is why the page always names the zone it's using instead of showing bare times.

Can I set availability until midnight?

Yes. An end time of midnight means the end of that day, and the window rolls into the following calendar day rather than collapsing to zero. Evening slots are also grouped under your local date, so a 9 PM slot appears on the day you'd expect even when it's already tomorrow in UTC.

Do hosts in different timezones need separate booking links?

No. Each host's hours are computed in their own timezone before anything is pooled, so one shared link works across a distributed team. It's worth knowing that a widely-spread pool naturally specializes — European mornings land on European hosts — so if you want a specific distribution, split the link by region deliberately.

Keep reading

Team scheduling

Pooled availability across a distributed team.

Neos Meet vs Calendly

Where we differ, feature by feature.

Switching schedulers

Rebuild your setup — and verify the timezone first.

Try it on your own calendar.

Sign in with Google and your booking page is live immediately — free, no card, cancel yourself any time.

Get started free