Skip to content

Commit c3682df

Browse files
committed
πŸ“– [docs][agents] Rewrite timestamp rules around the client timezone
1 parent 0781bfe commit c3682df

1 file changed

Lines changed: 38 additions & 11 deletions

File tree

β€Ž.agents/rules/timestamps.mdβ€Ž

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,42 @@ backend and frontend.
2222
value as naive local time.
2323
- Reject or treat as a bug any timestamp arriving without offset/zone info.
2424

25+
## Client timezone
26+
27+
The frontend renders and inputs in the **client timezone**: the browser zone by
28+
default, replaced by the user's saved override (Settings page, persisted in
29+
`localStorage`).
30+
31+
- Read it with `useClientTimezone()`, which always resolves to a zone and also
32+
reports `isOverridden`.
33+
- `BROWSER_TIMEZONE` is the provider's fallback, not a value call sites read on
34+
their own, and `Intl.DateTimeFormat().resolvedOptions().timeZone` never
35+
belongs in a component.
36+
- The override is a display and input preference only. It relabels instants, it
37+
never rewrites stored ones.
38+
2539
## Frontend rendering
2640

27-
- Render in the **browser timezone** by default.
41+
- Render in the **client timezone**.
2842
- Optionally offer a switch to render in the entity's associated timezone
29-
(account zone for transactions). Note the consequence: with browser-default
30-
rendering, a transaction's calendar day and statement bucket are
31-
viewer-dependent until the switch is used.
43+
(account zone for transactions). Note the consequence: with client-zone
44+
rendering, a transaction's calendar day and statement bucket follow the
45+
viewer's preference until the switch is used.
3246

3347
## Frontend create / edit
3448

35-
- The picker always reflects **browser local time**. The user inputs the instant
36-
as they experience it.
37-
- When the associated entity's zone differs from the browser zone, preview the
38-
same instant re-expressed in that zone (e.g. `toZonedISOString`) so the user
39-
sees which day/statement it lands in for the account.
49+
- The picker speaks the **client timezone**, which is the user's own clock, not
50+
necessarily the machine's. Picking Aug 7 12:00 AM with an `Asia/Taipei`
51+
override means Taipei midnight even when the browser sits in SF.
52+
- Every wall-clock read and write goes through the Temporal helpers in
53+
`lib/utils.ts` (`formatTimePart`, `zonedCalendarDate`, `withDate`,
54+
`withTime`), which all take an explicit `timeZone`. Native `Date` getters
55+
(`getHours`, `getFullYear`) are hardcoded to the browser zone, so they must
56+
not drive the picker.
57+
- When the associated entity's zone differs from the client zone, preview the
58+
same instant re-expressed in that zone (`toZonedISOString`, rendered by
59+
`ZonedTimePicker`) so the user sees which day/statement it lands in for the
60+
account.
4061
- **Re-expressing in the associated zone is a relabel of the same instant, never
4162
a reschedule.** 2:00 PM SF = 5:00 PM NYC = 22:00 UTC are one instant with three
4263
labels. Sending `22:00Z`, `-07:00`, or `-04:00` all persist the identical row.
@@ -45,9 +66,15 @@ backend and frontend.
4566

4667
## Worked example
4768

48-
A client in SF creates a transaction on an NYC account:
69+
A user whose client timezone resolves to `America/Los_Angeles` creates a
70+
transaction on an NYC account:
4971

50-
1. Picker shows SF local time. User picks 2:00 PM.
72+
1. Picker shows the client zone. User picks 2:00 PM.
5173
2. FE previews the account zone: 5:00 PM America/New_York (same instant).
5274
3. FE sends that instant (offset-aware ISO in the account zone).
5375
4. Postgres stores 22:00 UTC. Reads recover the zone from the account to render.
76+
77+
If that same user overrides their timezone to `Asia/Taipei`, step 1 changes
78+
meaning: 2:00 PM now names Taipei 2:00 PM (06:00 UTC), and the preview line and
79+
the stored row follow. The override changes which instant the input names. It
80+
does not touch instants already stored.

0 commit comments

Comments
Β (0)