fix(admin): deterministic UTC timestamp formatting to remove hydration mismatch

This commit is contained in:
Gerhard Scheikl
2026-05-31 12:26:41 +02:00
parent b6c4d94990
commit 61bf6c013c
2 changed files with 29 additions and 5 deletions
+27 -2
View File
@@ -11,9 +11,34 @@ export function formatBytes(n: number): string {
return `${v.toFixed(2)} ${units[i]}`;
}
export function formatDate(s: string | null | undefined): string {
function pad(n: number): string {
return n < 10 ? `0${n}` : `${n}`;
}
// Deterministic, timezone-independent date+time formatter.
// Uses UTC getters so the server (UTC) and client (local TZ) render
// byte-identical text, avoiding React hydration mismatches (error #425).
// Output format: "YYYY-MM-DD HH:MM UTC".
export function formatDateTime(s: string | null | undefined): string {
if (!s) return '—';
const d = new Date(s);
if (Number.isNaN(d.getTime())) return '—';
return d.toLocaleString();
const date = `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(
d.getUTCDate(),
)}`;
const time = `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`;
return `${date} ${time} UTC`;
}
// Date-only deterministic UTC formatter. Output format: "YYYY-MM-DD UTC".
export function formatDateOnly(s: string | null | undefined): string {
if (!s) return '—';
const d = new Date(s);
if (Number.isNaN(d.getTime())) return '—';
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(
d.getUTCDate(),
)} UTC`;
}
// Backwards-compatible alias: existing call sites render date+time.
export const formatDate = formatDateTime;