Any platform · Updated · 10 min read · Lurto

Voice agent books the wrong time: timezones, DST and double bookings

Quick answer

Four distinct faults produce a voice agent booking the wrong time, and they need different fixes: a UTC offset stored instead of the timezone, so every future booking made before a clock change lands an hour out; the hour that does not exist on spring-forward and the hour that happens twice on fall-back, both of which most date libraries accept without a word; check-then-book, where availability was read half a minute before the write went in; and a confirmation composed from what the agent intended rather than from what the booking system actually returned.

Booking time test cases (JSON)Twelve cases across real 2026 and 2027 daylight-saving transitions, with the exact UTC instant each one should produce. Every date in it was computed against the timezone database, not typed from memory.

The voice agent books the wrong time. Not always, not obviously, and never in the demo: an appointment lands an hour early, a caller in Arizona gets a slot that does not exist, or two people are told the same Tuesday at two is theirs. By the time anyone connects the complaints to a pattern, the calendar has been quietly wrong for weeks and nobody trusts it.

Four distinct faults produce this symptom, and they need different fixes. Below is each one with the trace it leaves, the specific dates in 2026 and 2027 where it will bite, and a set of test cases you can run against your own booking path this afternoon.

1. The offset is stored instead of the zone

This is the most common and the least visible. Somewhere between the model saying "Tuesday at two" and the row landing in the calendar, the time is turned into a fixed offset. It works perfectly until the clocks move, and then every future booking made before the change is an hour out.

// what the agent extracted
{ "intent": "book", "spoken": "Tuesday at 2pm", "caller_tz": "America/New_York" }

// what got written
{ "start": "2026-03-10T14:00:00-05:00" }   // EST offset, stored on 2026-03-05

// what the calendar shows on the day
2026-03-10 13:00 EDT   // one hour early, because the zone changed on 03-08

The value is not wrong when it is written. It becomes wrong on 8 March 2026, when US Eastern moves to UTC-4 and the frozen -05:00 no longer describes New York. A booking is an intention about a wall clock in a place, so the place is what has to be stored: America/New_York plus a local time, resolved to an instant at read time by a library reading a current timezone database.

The dates to test against, since they are not the same on both sides of the Atlantic: US clocks change on 8 March and 1 November 2026, and again on 14 March 2027. UK and EU clocks change on 29 March and 25 October 2026. For roughly three weeks each spring the usual five-hour gap between London and New York is four, which is where transatlantic bookings go wrong even when both systems are individually correct.

2. The hour that does not exist, and the hour that happens twice

On the morning US clocks go forward, the local time 02:30 never occurs. On the morning they go back, 01:30 occurs twice. A caller can ask for either, and most date libraries will accept both without a word.

>>> datetime(2026, 3, 8, 2, 30, tzinfo=ZoneInfo("America/New_York"))
datetime.datetime(2026, 3, 8, 2, 30, tzinfo=ZoneInfo(key='America/New_York'))

>>> _.astimezone(timezone.utc)
datetime.datetime(2026, 3, 8, 7, 30, tzinfo=datetime.timezone.utc)

No error, no warning, an instant invented out of a time that did not happen. The ambiguous case is worse because both answers are defensible: 01:30 on 1 November 2026 is a real local time twice over, an hour apart in UTC, and whichever your library picks it will pick silently.

A booking agent has an advantage here that a batch job does not: there is a person on the line. The correct behaviour is to notice and ask. "That hour does not exist on that date because the clocks move, I can do half past one or half past three" is a sentence a caller accepts without noticing anything went wrong.

3. Check-then-book, with a gap in the middle

Two callers get the same slot because availability was read, a conversation happened, and the write went in against a world that had changed. A receptionist we built did this in its second week.

[14:02:11] call_a  get_availability      -> ["14:30","15:00","15:30"]
[14:02:14] call_b  get_availability      -> ["14:30","15:00","15:30"]
[14:02:41] call_a  create_event 14:30    -> 201 Created  evt_8812
[14:02:58] call_b  create_event 14:30    -> 201 Created  evt_8813   // no conflict raised

Twenty-nine seconds of conversation sit between the read and the write, and most calendar APIs will happily create an overlapping event because overlapping events are legal. The fix is not a longer lock, it is a re-check at the moment of writing, with the failure treated as a normal conversational turn rather than an error: "that one just went, I have half past two or four o'clock instead." Where the API supports a conditional create or an idempotency key, use it; where it does not, read again immediately before writing and accept that the window is now under a second instead of half a minute.

4. The confirmation is generated, not read back

The worst version of this failure is the one where the booking never existed at all. The model composes a confident confirmation from what it intended to do, the write fails, and the caller hangs up believing they have an appointment.

[09:41:02] tool create_event   -> 429 Too Many Requests
[09:41:02] tool result         -> {"error":"rate_limited"}
[09:41:04] assistant           -> "You're all set for Thursday at 10. See you then."

Nothing is broken in a way monitoring can see: the call completed, the transcript reads well, the customer is satisfied until Thursday. The rule that prevents it is narrow and absolute. The confirmation sentence must be generated from the booking system's response, never from the request, and a failed write has to become something the caller hears. On any error the agent should retry once, and if it still fails, say a person will confirm by email and make that true by raising a task.

Run the twelve cases before you change anything

The attached file contains twelve booking cases with the exact UTC instant each should produce, computed against the timezone database rather than typed from memory. They cover both spring-forward and fall-back on both sides of the Atlantic, the three-week window where the offsets are out of step, the southern hemisphere running the other way, and the half-hour and three-quarter-hour offsets in India and Nepal that break arithmetic written for whole hours.

Feed each case through the same path a caller uses, including the model, not straight to your date library. Most of the bugs above live in the handoff between the two. The two cases marked as gap and ambiguous have no single right answer, and that is deliberate: what you are testing is whether your system notices and asks, or guesses quietly.

When not to hire anyone

If your agent serves one timezone, never books across a DST boundary, and writes to a calendar nobody else touches, three of these four faults cannot happen to you. Store the zone anyway, because that costs nothing today and everything later, and move on.

If you are seeing exactly one wrong booking around one date, run the test cases, fix the offset storage, and you are done. That is an afternoon of work and it does not need us.

The case for help is when several of these overlap: bookings across zones, a shared calendar, and a confirmation the caller has already acted on. Untangling which of the four caused a specific complaint takes reading the call transcript alongside the API log alongside the calendar's own history, and by the time it is worth doing there are usually months of bad data to reconcile as well as code to change.

What it costs to have us do it

A written diagnostic is $500£400€450, delivered in two business days, credited in full against whatever follows and refunded if it names no fixable cause. For this symptom that means we run the test cases against your booking path, read a sample of real calls against what the calendar actually holds, and tell you which of the four faults you have and how many bookings it has already touched.

Repairs land between $750£600€700 and $1,500£1,200€1,400 when it is one fault, and $1,500£1,200€1,400 to $4,000£3,100€3,700 when the booking path needs restructuring around a re-check and a proper confirmation. Every fix ships with the test cases wired into your release process, because the reason this bug comes back is that nothing was watching for it the first time.

Questions people ask about this

Why do bookings drift by exactly one hour?

Because a fixed offset was stored instead of a place. An appointment written as 2026-03-10T14:00:00-05:00 is correct on the day it is written and wrong on 8 March 2026, when US Eastern moves to UTC-4 and the frozen -05:00 no longer describes New York. A booking is an intention about a wall clock in a place, so store America/New_York plus a local time and resolve it to an instant at read time against a current timezone database.

Which dates should we test against?

US clocks change on 8 March and 1 November 2026, and again on 14 March 2027. UK and EU clocks change on 29 March and 25 October 2026. For roughly three weeks each spring the usual five-hour gap between London and New York is four, which is where transatlantic bookings go wrong even when both systems are individually correct.

What should the agent do when a caller asks for an hour that does not exist?

Notice and ask, which is an advantage a booking agent has over a batch job because there is a person on the line. On the morning clocks go forward, 02:30 never occurs; on the morning they go back, 01:30 occurs twice and both answers are defensible an hour apart in UTC. Most date libraries will accept either silently. That hour does not exist on that date because the clocks move, I can do half past one or half past three is a sentence a caller accepts without noticing anything went wrong.

How do two callers end up with the same slot?

Availability was read, a conversation happened, and the write went in against a world that had changed, often with twenty to thirty seconds between the two, and most calendar APIs will happily create an overlapping event because overlapping events are legal. The fix is not a longer lock but a re-check at the moment of writing, with the failure treated as a normal conversational turn: that one just went, I have half past two or four o'clock instead.

The caller was confirmed and no appointment exists. How?

The confirmation was composed from the request rather than the response. The write failed, a 429, a timeout, and the model produced a confident confirmation anyway, so the call completed, the transcript reads well, and the customer is satisfied until Thursday. The rule is narrow and absolute: the confirmation sentence must be generated from the booking system's response, never from the request. On any error, retry once, then say a person will confirm by email and make that true by raising a task.

What each band includes

Every band below is a price agreed in writing before any invoice. The diagnostic comes off the repair in full, so if you go ahead you have paid nothing extra for the reading.

BandPriceTime
Written diagnosticWe read the workflows, logs, and prompts. Written root-cause report and a fixed repair quote. Credited in full against the fix, and refunded if it cannot name a fixable cause.from $500from £400from €4502 business days
Small fixOne clear failure: a broken integration, a bad prompt, a missing retry. When the diagnostic shows a minor break, you pay the minor price.$750-$1,500£600-£1,200€700-€1,4002-5 days
Standard rescueWhere most rescues land. Several failure points or a fragile architecture: root-cause fixes, error handling, alerts, and a trail you can audit.$1,500-$4,000£1,200-£3,100€1,400-€3,7001-2 weeks
RebuildOnly when repairing costs more than starting over. The diagnostic says so in writing, with both numbers, before you decide.$4,000-$10,000£3,100-£7,800€3,700-€9,2002-4 weeks

Full detail on the rescue page, and every other number we charge is on the pricing page.

Other symptoms we have written up

Longer reading

Send us the execution log and we will tell you what broke

Two business days and a price at the end of it. If the fix is small enough to do yourself, the report will say so.