store-user-timezone-and-render-locally
Use when a product shows times to a user — store the IANA zone name the user chose and render every timestamp in it, never store a fixed offset.
- License 许可
- MIT
- 最近更新
- 2026-11-11
- Stars
- ★ 80
- Forks
- 17
01 前言 Front Matter
- name
- store-user-timezone-and-render-locally
- description
- Use when a product shows times to a user — store the IANA zone name the user chose and render every timestamp in it, never store a fixed offset.
02 资源文件 3
- 许可证LICENSE1.0 KB
- 参考文档SOURCE.md364 B
- 参考文档TRUST.auto.yaml2.2 KB
03 SKILL.md 正文
Store the user timezone and render locally
Users think in their own local time and expect the product to do the same. Store the IANA zone name once, render every timestamp through it, and the display stays correct across DST without per-row math.
Procedure
- Capture the zone name, not the offset, and not the browser's abbreviation (
ESTis ambiguous across the world):
Intl.DateTimeFormat().resolvedOptions().timeZone // "America/New_York"
- Persist it as a column with a default of UTC and validate against the tz database:
python3 -c "import zoneinfo,sys; zoneinfo.ZoneInfo(sys.argv[1])" America/New_York
- Let the user override it explicitly; do not re-detect on every login, or a travelling user's logs jump zones.
- Store every instant in UTC and convert only at the render edge:
from zoneinfo import ZoneInfo
def render(dt_utc, zone):
return dt_utc.astimezone(ZoneInfo(zone)).strftime("%Y-%m-%d %H:%M %Z")
- Render with the zone label so the user is never guessing:
2026-03-01 09:00 EST, not2026-03-01 09:00. - For date-only displays (due dates, birthdays), keep the value as a civil date, not an instant — an instant rendered in a western zone can slip a day for users east of UTC.
- Re-render on zone change and cache with the zone in the key, so a user in two zones does not see another's formatting:
cache_key = f"render:{user_id}:{zone}:{instant_epoch}"
- Backfill: for existing rows with no zone, default to UTC and flag them for the user to confirm at next login.
Pitfalls
- Storing
-05:00freezes the user in winter time; six months later their 09:00 shows as 08:00 because the offset never shifted. toLocaleString()without an explicit zone uses the server's or runtime's zone in SSR, so the same page renders differently on the server and the client — a hydration mismatch.- Emails generated server-side with no zone land at odd hours for the recipient; resolve the recipient's zone before formatting.
- A user who moves regions may want history in their old zone; storing only the current zone loses that. Consider a per-event zone for anything legally timestamped.
- Date-only fields converted through UTC can move a day; keep them as
DATEand never run them through a zone.
Verification
psql -c "SELECT count(*) FROM users WHERE timezone IS NULL OR timezone !~ '^[A-Za-z]+/[A-Za-z_]+$';"
Returns 0 = every user has a valid IANA zone name. Report: "users.timezone stores IANA names; render path converts UTC to the user's zone with a %Z label; server and client output match."
04 同仓库更多 Skills
recipe-performance
Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold/warm/background-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout/paint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.
mexc-spot-websocket
MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.
mexc-spot-rest
MEXC Spot REST workflows for public data, signed account requests, orders, wallet/admin actions, and secure signing without exposing API keys.
mexc-futures-websocket
MEXC Futures WebSocket workflows for public streams, private account/order/position streams, ping/pong, subscriptions, and depth maintenance.
0xklen-version-and-refresh-sanctions-lists
暂无简介
verify-tests-cover-changed-lines
Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.