fix(social-image): Uhrzeit/Datum in Europe/Berlin rendern
Deploy / verify (push) Successful in 1m14s
Deploy / deploy (push) Successful in 2m8s

Social-Image-Generierung lief SSR auf Server-TZ (UTC) → terminZeit
"10:00+02:00" wurde als "08:00" aufs Bild gerendert (−2h im Sommer).
toLocaleDate/TimeString in Kalender- und Post-Route auf timeZone
"Europe/Berlin" gepinnt. Cache-Version v26→v27 invalidiert alte PNGs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-06-19 13:20:01 +02:00
parent 781869b2b4
commit fdc18ab5b8
2 changed files with 10 additions and 4 deletions
@@ -97,18 +97,23 @@ async function loadFonts() {
return fontCache;
}
// terminZeit ist mit Offset gespeichert (z. B. 10:00+02:00 = 08:00 UTC).
// Rendering muss in Europe/Berlin erzwungen werden — sonst rendert der
// SSR-Prozess (Server-TZ = UTC) 2h zu früh (10 Uhr → 8 Uhr auf dem Bild).
const TZ = "Europe/Berlin";
function formatDate(iso: string | undefined): { date: string; time: string | null } {
if (!iso) return { date: "", time: null };
const d = new Date(iso);
const date = d.toLocaleDateString("de-DE", { day: "2-digit", month: "long", year: "numeric" });
const date = d.toLocaleDateString("de-DE", { day: "2-digit", month: "long", year: "numeric", timeZone: TZ });
const hasTime = !/T00:00:00/.test(iso);
const time = hasTime ? d.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" }) : null;
const time = hasTime ? d.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit", timeZone: TZ }) : null;
return { date, time };
}
function weekday(iso: string | undefined): string {
if (!iso) return "";
return new Date(iso).toLocaleDateString("de-DE", { weekday: "long" });
return new Date(iso).toLocaleDateString("de-DE", { weekday: "long", timeZone: TZ });
}
/**
@@ -139,7 +144,7 @@ async function loadEventImage(
const cache = new Map<string, { png: Buffer; ts: number }>();
const CACHE_TTL = 10 * 60_000; // 10min
const CACHE_VERSION = "v26";
const CACHE_VERSION = "v27";
function parseFormat(v: string | null): Format {
if (v === "square") return "square";
@@ -90,6 +90,7 @@ function formatDateLong(iso: string | undefined | null): string {
day: "2-digit",
month: "long",
year: "numeric",
timeZone: "Europe/Berlin",
});
} catch {
return "";