// Datums- und Formatierungshelfer für den Wochenplan (Mo–Fr). // Alle Berechnungen laufen über UTC, damit Server und Browser // unabhängig von der Zeitzone dieselbe Woche ermitteln. import type { MenuEntry } from "./types"; const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/; function toDate(iso: string): Date { return new Date(`${iso}T00:00:00Z`); } export function toISO(d: Date): string { return d.toISOString().slice(0, 10); } /** Montag der Woche, in der `iso` liegt (bzw. der aktuellen Woche). */ export function mondayOf(iso?: string | null): string { const base = iso && ISO_DATE.test(iso) ? toDate(iso) : new Date(); const day = (base.getUTCDay() + 6) % 7; // Montag = 0 const monday = new Date( Date.UTC(base.getUTCFullYear(), base.getUTCMonth(), base.getUTCDate() - day) ); return toISO(monday); } export function addDays(iso: string, days: number): string { const d = toDate(iso); d.setUTCDate(d.getUTCDate() + days); return toISO(d); } /** Heutiges Datum als YYYY-MM-DD (UTC). */ export function todayISO(): string { return toISO(new Date()); } /** Index (0=Montag…4=Freitag) von `iso` innerhalb seiner Woche, sonst -1 (Wochenende). */ export function weekdayIndex(iso: string): number { const day = (toDate(iso).getUTCDay() + 6) % 7; return day <= 4 ? day : -1; } /** z. B. "13. Juli 2026" (dateLocale z. B. "de-DE", "en-GB", "pl-PL") */ export function formatDateLong(iso: string, dateLocale: string): string { return toDate(iso).toLocaleDateString(dateLocale, { day: "numeric", month: "long", year: "numeric", timeZone: "UTC", }); } /** z. B. "3,50€" */ export function formatPrice(price: number | string): string { return Number(price).toFixed(2).replace(".", ",") + "€"; } /** Allergen-/Zusatzstoff-Kürzel eines Gerichts, z. B. "A,G,2" */ export function dishCodes(dish: { allergens: string[]; additives: string[] }): string { return [...(dish.allergens ?? []), ...(dish.additives ?? [])].join(","); } /** Einträge eines Tages/einer Essenszeit aus der geladenen Wochenliste herausfiltern. */ export function entriesFor( entries: MenuEntry[], iso: string, sectionKey: string ): MenuEntry[] { return entries.filter((e) => e.menu_date === iso && e.section_key === sectionKey); }