SEV-378: add tolerant formatDate/formatDateTime to shared (v0.3.0)

Our Go/Turso layer emits SQLite datetime('now') as "YYYY-MM-DD HH:MM:SS"
(UTC, no zone), which new Date() can't parse → "Invalid Date" in admin.
formatDate/formatDateTime normalize that shape (space→T + Z) and RFC3339,
returning '' for falsy/invalid. Tests cover both formats + empties.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bastian de Byl
2026-06-10 16:36:24 -04:00
parent 2b54028495
commit e405985c34
4 changed files with 47 additions and 2 deletions
+26
View File
@@ -95,3 +95,29 @@ export function vehicleName({ year, make, model, commissioned } = {}, fallback =
const v = [year, make, model].filter(Boolean).join(' ');
return v || fallback;
}
// SEV-378: our Go/Turso layer emits SQLite `datetime('now')` timestamps as
// "YYYY-MM-DD HH:MM:SS" (UTC, no zone), which `new Date()` can't reliably
// parse → "Invalid Date" in the admin UI. normalizeTs handles both that shape
// and RFC3339; returns null for falsy/invalid so callers render ''.
function normalizeTs(ts) {
if (!ts) return null;
const s = String(ts).trim();
const sqlite = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(s);
const d = new Date(sqlite ? s.replace(' ', 'T') + 'Z' : s);
return isNaN(d.getTime()) ? null : d;
}
/** Localized date (e.g. "Jun 10, 2026"). '' for missing/invalid input. */
export function formatDate(ts) {
const d = normalizeTs(ts);
return d ? d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '';
}
/** Localized date + time (e.g. "Jun 10, 2026, 2:42 PM"). '' for missing/invalid. */
export function formatDateTime(ts) {
const d = normalizeTs(ts);
return d
? d.toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' })
: '';
}