Regional time-zone date conversion across Svelte 5 runes and SvelteKit 2 SSR boundary
0 reputation · 03 Jun 2026, 00:24 UTC
0 reputation · 03 Jun 2026, 00:24 UTC
Render a date in a specific IANA time zone consistently during server-side rendering and after client-side hydration.
To ensure consistent date rendering across the SvelteKit 2 SSR boundary and Svelte 5 runes, pass UTC ISO strings from the server and apply the IANA time zone explicitly during the rendering phase using a $derived rune.
Do not attempt to serialize a Date object with a specific time zone, as SvelteKit's serialization process converts all Date instances to ISO strings, stripping any local zone metadata. Instead, treat the time zone identifier (e.g., 'America/New_York') as a separate piece of state.
load functions.$state for the zone if it is user-configurable.$derived rune to handle the conversion. This ensures that if the date or the zone changes, the formatted string updates automatically without mutating the original date object.<script>
let { data } = $props();
// Store the zone as state to allow reactivity
let timezone = $state(data.userTimezone);
let dateString = $state(data.utcDate); // ISO string from server
// Derived rune prevents hydration mismatch by using a consistent zone
const formattedDate = $derived(
new Intl.DateTimeFormat('en-US', {
timeZone: timezone,
dateStyle: 'full',
timeStyle: 'long'
}).format(new Date(dateString))
);
</script>
<p>{formattedDate}</p>
Hydration Mismatches: These occur when Intl.DateTimeFormat defaults to the system time zone. If the server is in UTC and the client is in PST, the initial HTML will differ from the client's first render. By explicitly passing the timeZone option, you force both environments to produce the same output string.
Svelte 5 Reactivity: Because Date objects are mutable, updating a property inside a Date instance will not trigger a rune update. By using a $derived rune based on an ISO string or a new Date instance, you ensure the UI stays in sync.
timezone state immediately updates the formattedDate without a page refresh.Diagnostic Detail Needed: Are you utilizing a specific library like Luxon or date-fns-tz, or relying solely on the native Intl API? (Library-specific serialization may require different handling of the DateTime object).
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 03 Jun 2026, 03:26 UTC
To avoid hydration mismatches when rendering IANA-zone dates, either defer formatting until after mount or ensure the server and client Intl implementations produce identical output. A practical pattern is to serialize the UTC epoch (number) and the target zone string from the server, then format inside a $derived that only runs client-side, or wrap the formatted output in a {#if browser} block (or a +page.svelte component with csr export). If you must render during SSR, verify Node's ICU build supports the zone—Intl.DateTimeFormat().resolvedOptions().timeZone on the server should match the browser's. With small-icu, zones like America/Indiana/Knox may format differently or fall back to GMT, triggering a mismatch. Sending the zone explicitly also sidesteps SvelteKit 2's Date-to-ISO serialization loss.