// Datumshilfen. Kalendertage sind Strings 'YYYY-MM-DD', Uhrzeiten 'HH:MM'. // Monate sind 0-basiert wie bei JS Date. export const WEEKDAYS = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']; export const MONTHS = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']; function pad(n) { return String(n).padStart(2, '0'); } export function toDateString(date) { return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`; } export function fromDateString(s) { const [y, m, d] = s.split('-').map(Number); return new Date(y, m - 1, d); } export function today() { return toDateString(new Date()); } export function addDays(s, n) { const date = fromDateString(s); date.setDate(date.getDate() + n); return toDateString(date); } // Montag der Woche, in der s liegt. export function startOfWeek(s) { const date = fromDateString(s); const offset = (date.getDay() + 6) % 7; return addDays(s, -offset); } export function weekDays(s) { const monday = startOfWeek(s); return Array.from({length: 7}, (_, i) => addDays(monday, i)); } // 42 Tage (6 Wochen) ab dem Montag der Woche des Monatsersten. export function monthGrid(year, month) { const first = toDateString(new Date(year, month, 1)); const start = startOfWeek(first); return Array.from({length: 42}, (_, i) => addDays(start, i)); } export function isoWeek(s) { const date = fromDateString(s); // Der Donnerstag derselben Woche bestimmt das ISO-Jahr. const thursday = new Date(date); thursday.setDate(date.getDate() - ((date.getDay() + 6) % 7) + 3); const firstThursday = new Date(thursday.getFullYear(), 0, 4); firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3); return 1 + Math.round((thursday - firstThursday) / (7 * 24 * 3600 * 1000)); } export function formatMonth(year, month) { return `${MONTHS[month]} ${year}`; } // 'Do, 17.09.2026' export function formatDate(s) { const date = fromDateString(s); return `${WEEKDAYS[(date.getDay() + 6) % 7]}, ${formatDateInput(s)}`; } // '17.09.2026' export function formatDateInput(s) { const [y, m, d] = s.split('-'); return `${d}.${m}.${y}`; } // '17.09.' export function formatDayMonth(s) { const [, m, d] = s.split('-'); return `${d}.${m}.`; } // Akzeptiert '17.09.2026', '17.9.26', '17.9.' (aktuelles Jahr) und '2026-09-17'. export function parseDateInput(text) { const t = text.trim(); let y, m, d; let match = t.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2,4})?$/); if (match) { d = Number(match[1]); m = Number(match[2]); y = match[3] === undefined ? new Date().getFullYear() : Number(match[3]); if (y < 100) y += 2000; } else { match = t.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/); if (!match) return null; [y, m, d] = [Number(match[1]), Number(match[2]), Number(match[3])]; } const date = new Date(y, m - 1, d); if (date.getFullYear() !== y || date.getMonth() !== m - 1 || date.getDate() !== d) return null; return toDateString(date); } // Akzeptiert '9:00', '09:00', '9.30', '14' → 'HH:MM'. export function parseTimeInput(text) { const match = text.trim().match(/^(\d{1,2})(?:[:.](\d{2}))?$/); if (!match) return null; const h = Number(match[1]); const min = match[2] === undefined ? 0 : Number(match[2]); if (h > 23 || min > 59) return null; return `${pad(h)}:${pad(min)}`; } export function timeToMinutes(t) { const [h, m] = t.split(':').map(Number); return h * 60 + m; } export function minutesToTime(minutes) { return `${pad(Math.floor(minutes / 60))}:${pad(minutes % 60)}`; } export function hourOf(t) { return Number(t.split(':')[0]); }