Explain Time-Zone Requirements Before Asking an Agent to Fix Dates

Drafted and reviewed using AI assistance.

On this page

Before asking an agent to fix a time-zone bug, say what must stay the same: a moment on the timeline, a local clock reading or a calendar date. Those are different requirements. Converting everything to UTC without preserving the original meaning can turn a display fix into a scheduling error.

This guide uses two fictional features: a cross-region meeting and a date-only submission deadline. The listed conversions were executed locally with Python 3.12.14 and system IANA time-zone data 2026c. They are small teaching examples, not tests of a browser or a scheduling product.

Name the object you are changing

Object Example requirement What to preserve
Instant Everyone joins one meeting simultaneously One moment; each viewer may see a different clock time
Recurring local wall time A team meets at 09:00 in New York every Monday Local time, recurrence rule and named zone; the UTC offset can change
Calendar date Submissions are accepted through November 1 in New York The date, governing zone and explicit cutoff rule

A birthday may be a date with no governing time zone at all. A submission deadline needs a zone because the application must decide when that date ends. Do not add a UTC midnight to either field simply because the database accepts timestamps.

If a user reports “the date is wrong,” ask which of these objects the field represents before changing storage or display code. Also establish where the zone comes from: an explicit selection, a saved project setting or the viewer's environment. Those choices produce different behavior for a traveler opening the same record.

Case 1: one meeting, three displays

The fictional meeting occurs at 2026-07-15T13:00:00Z. Its instant is fixed; the viewer zone only changes the display.

Viewer zone Display for the same instant
America/New_York July 15, 2026, 09:00, UTC−04:00
Europe/London July 15, 2026, 14:00, UTC+01:00
Asia/Tokyo July 15, 2026, 22:00, UTC+09:00

Those offsets apply to that instant under the time-zone data used in this exercise. They are not year-round constants. Retain a named zone when future local-time rules matter.

The Python zoneinfo documentation describes IANA-zone support, ambiguous-time handling through fold, and time-zone data lookup. A deployment needs an available, known data source; this exercise used system files, not a newly installed package. Record the runtime and data version alongside reproducible cases.

Decide what happens when a clock time does not identify one instant

In New York, 2026-03-08 02:30 is a missing local time during the spring transition. In the local example, round-trip classification found zero matching instants.

On 2026-11-01, 01:30 occurs twice:

User's wall time Offset Corresponding UTC instant
November 1, 01:30, earlier occurrence UTC−04:00 2026-11-01T05:30:00Z
November 1, 01:30, later occurrence UTC−05:00 2026-11-01T06:30:00Z

For this fictional meeting editor, choose this policy: ask for another valid time when the selected wall time is missing; ask the user to choose the earlier or later occurrence when it repeats. Show the offset and UTC equivalent next to the choice. Other products can choose another documented policy, but the agent should not make that business decision silently.

Attaching a zone with replace(tzinfo=...) does not itself reject an impossible wall time. This small classifier checks both folds, round-trips through UTC and deduplicates matching instants:

from datetime import datetime, timezone
from zoneinfo import ZoneInfo

def possible_instants(wall, zone):
    # wall is a naive datetime representing the requested local clock time.
    found = set()
    for fold in (0, 1):
        candidate = wall.replace(tzinfo=zone, fold=fold)
        instant = candidate.astimezone(timezone.utc)
        returned = instant.astimezone(zone)
        if returned.replace(tzinfo=None) == wall:
            found.add(instant)
    return sorted(found)

zone = ZoneInfo("America/New_York")
assert possible_instants(datetime(2026, 3, 8, 2, 30), zone) == []
assert len(possible_instants(datetime(2026, 11, 1, 1, 30), zone)) == 2

The companion exercise used this classification approach and checked both exact UTC values. This is a small helper with a naive-datetime input contract, not a complete user-input parser or recurrence engine.

Case 2: a deadline that lasts 25 hours

Suppose the fictional form accepts submissions throughout November 1, 2026 in America/New_York. Its chosen cutoff is the next local midnight, exclusive.

Boundary UTC instant
November 1 local midnight, inclusive 2026-11-01T04:00:00Z
November 2 local midnight, exclusive 2026-11-02T05:00:00Z

The elapsed interval is 25 hours in this example. Adding 24 hours to the starting instant would close the form one hour before the intended next local midnight.

Store the deadline's date, governing zone and cutoff rule. Resolve its boundary using the relevant rules rather than treating the date as midnight UTC. At comparison time, a submission at or after the exclusive end is closed. This avoids an invented “last millisecond of the day,” whose precision may differ across systems.

Define the authoritative clock too. For this example, the server decides acceptance; a browser countdown is an aid and does not override the cutoff. Time-zone data changes and future recurring schedules need a separate update policy. Do not imply that the tiny examples above implement one.

A brief for the agent

Fix the fictional meeting editor and date-only submission cutoff.
First identify each field's meaning; do not change labels alone.

Meeting contract:
- A saved one-off meeting represents one instant.
- Viewer zones change display, not the saved instant.
- A newly entered local time includes an explicit IANA zone.
- Missing wall time: ask the user to choose another valid time.
- Repeated wall time: ask for earlier/later occurrence and show offset/UTC.
- Do not infer a permanent offset from one example.

Deadline contract:
- Store date 2026-11-01 with America/New_York and a next-midnight rule.
- Its exclusive end is 2026-11-02T05:00:00Z under the exercise's rules.
- Server comparisons decide acceptance; at or after the end is closed.
- Derive the next local midnight; do not add 24 elapsed hours.

Acceptance cases:
- 2026-07-15T13:00:00Z displays as 09:00 New York, 14:00 London,
  and 22:00 Tokyo on that date.
- New York 2026-03-08 02:30 has no candidate instant.
- New York 2026-11-01 01:30 has candidates 05:30Z and 06:30Z.
- The specified deadline interval is 04:00Z Nov 1 to 05:00Z Nov 2.
- Check one instant just before cutoff and the exact cutoff separately.

Deliver the field model, conversion paths, ambiguity handling and checks.
Record the actual runtime and IANA data used, plus any unavailable checks.
Preserve unrelated fields. Recurrence, browser API replacement and database
migration are outside this change; raise dependencies before extending it.

A good fix makes the same business rule survive storage, editing and display. Start with that rule; the timestamp format is only one part of implementing it.