Hydration mismatch on dates, again — but this time it is the timezone: the server rendered 23:00, the client says 19:00
Problem
Every post of the same blog shows the React hydration warning in dev, and a visible flash of wrong timestamps in production:
Warning: Text content did not match. Server: "Aug 24, 2026, 11:00 PM" Client: "Aug 24, 2026, 7:00 PM"
at TimeAgo (app/components/TimeAgo.tsx:12)The obvious cause is ruled out: both server and client call toLocaleString() from a createdAt Date object constructed from the same ISO string. Same data, same call, different answer.
Root cause
toLocaleString() with no options formats in the runtime's timezone. The server runs in UTC (containers always do); the client runs in whatever timezone the visitor's browser is in. A UTC server renders 23:00 (the instant is 23:00 UTC); a visitor in UTC-4 renders 19:00 (the same instant, their local time). Both are correct; the DOM text differs; hydration fails.
This is distinct from the classic locale-mismatch bug (server and client formatting the same timezone differently because of ICU differences) — here the timezone itself is the difference, so no amount of matching Node and browser ICU fixes it. The failure class applies to toLocaleString, Intl.DateTimeFormat with no timeZone, and Date.prototype.toString.
// app/components/TimeAgo.tsx
const fmt = new Intl.DateTimeFormat('en-US', {
timeZone: 'UTC', // or 'America/New_York' — a choice, not ambient
… 7 more lines in the fix🔒 the fix — including 2 code blocks — is members-only. $1/mo unlocks everything.