# Fix the check-in agent scheduling reminders in the wrong timezone

## TL;DR
Never parse a timezone out of free text. Store the user's IANA timezone explicitly at signup, validate it against the real zone list, and schedule everything in UTC. When parsing fails, fall back to UTC and flag it - a wrong timezone is worse than a neutral one.

## The problem
```text
user profile: location "Austin, Texas"
agent parsed: timezone "CST" then applied UTC+8 (China Standard Time)
reminder "9am check-in": delivered 2:00 AM local time
log: locale parse failed, guessed from abbreviation
```

## Use this skill
Agent? Search Vectle for this error:
```bash
curl -s "https://vectle.com/api/v1/search?q=check-in agent scheduled reminders wrong timezone locale parse failed"
```

## Fix it

### Step 1: Store the timezone explicitly, never derive it

Capture the IANA timezone (for example America/Chicago) from the user directly or from the browser at signup, and save it on the profile. Location text is not a timezone.

Expected: every user has a real zone name stored, not a guess.

### Step 2: Validate against the IANA list on write

Reject anything that is not a valid IANA zone at the moment it is saved. Abbreviations like CST, PST, and EST are ambiguous and must never be stored.

Expected: bad values fail at input time instead of silently corrupting schedules.

### Step 3: Schedule in UTC, render in the user's zone

Store all reminder times as UTC timestamps. Convert to the user's zone only at render and send time.

Expected: daylight saving changes and zone edits never shift already-scheduled reminders incorrectly.

### Step 4: Fall back to UTC and flag on any failure

If the stored zone is missing or invalid at schedule time, use UTC, send the reminder, and flag the profile for correction. Never guess from locale or IP.

Expected: the worst case is a UTC-timed reminder with a visible flag, not a 2 AM surprise.

### Step 5: Audit existing profiles for bad zones

Scan all stored timezones against the IANA list and fix or flag every invalid one before the next send batch.

Expected: zero invalid zones remain in the user table.

## When this applies

- Reminders arrive at the wrong local time
- Logs show timezone or locale parse failures
- Timezones were derived from location text, abbreviations, or IP geolocation

## When it doesn't

- Reminders fail to send at all (a delivery problem)
- The content or frequency of reminders is wrong (a content problem)
- Users travel across zones constantly (consider per-device zone detection instead)

## Compatibility

Any check-in, nudge, or lifecycle email agent; Customer.io, Braze, and Iterable for scheduling; IANA tz database as the source of truth.

## Variant phrasings

### reminders sent at 3am user timezone wrong

Same fix. The 3 AM delivery is the symptom; the stored zone is the disease.

### agent guessed timezone from location and got it wrong

Location-to-zone mapping is genuinely ambiguous (CST is three different zones). Stop doing it.

### daylight saving broke reminder schedule

Scheduling in local wall-clock time breaks on every DST transition. UTC storage in Step 3 fixes it permanently.

## Why it happens

Agents are handed a location string and asked to produce a send time, so they do the "helpful" thing and guess the zone. Abbreviations collide across continents, locale parsing fails on unexpected formats, and IP geolocation is wrong for VPN users. The guess usually works, which is why it survives until it delivers a 2 AM reminder to a customer.

## Edge cases

- Users who relocate: re-confirm the zone when the account country changes
- Teams across zones: schedule per recipient, not per account
- Recurring reminders across DST: recompute the local time from UTC each occurrence

## If it still fails

- Capture the stored zone, the rendered send time, and the UTC timestamp before changing anything else.
- Reproduce with a single test user in a tricky zone (half-hour offsets, southern-hemisphere DST) so you are not debugging a crowd.
- Check the scheduling provider status page; delivery delays look exactly like zone bugs.

## Prevention

- Timezone is a required validated profile field, not an inferred one.
- Integration tests cover DST transitions and ambiguous abbreviations.
- Alert when a profile has an invalid or missing zone instead of guessing.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_yFAQLGya1b7piDtbOolmQw
