// Hilfsfunktionen für Zeit-/Datumsberechnungen rund um das Arbeitszeitkonto. const WEEKDAY_NAMES = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']; /** "08:30" -> 510 (Minuten seit Mitternacht) */ function timeToMinutes(value) { const [h, m] = String(value).split(':').map(Number); return h * 60 + m; } /** 95 -> "1:35" (immer positiv, ohne Vorzeichen) */ function minutesToHM(totalMinutes) { const abs = Math.abs(Math.round(totalMinutes)); const h = Math.floor(abs / 60); const m = abs % 60; return `${h}:${String(m).padStart(2, '0')}`; } /** 95 -> "+1:35", -30 -> "-0:30" */ function formatBalance(minutes) { const sign = minutes < 0 ? '−' : '+'; return `${sign}${minutesToHM(minutes)}`; } /** Prüft, ob ein Datum (YYYY-MM-DD) laut Einstellungen ein Arbeitstag ist. */ function isWorkDay(dateStr, workDays) { const day = new Date(`${dateStr}T00:00:00`).getDay(); return Array.isArray(workDays) && workDays.includes(day); } /** * Summiert alle Einzelpausen. * @param {Array<{start: string, end: string}>} breaks * @returns {number} Gesamte Pausenzeit in Minuten */ function computeTotalBreakMinutes(breaks) { if (!Array.isArray(breaks)) return 0; return breaks.reduce((total, b) => { if (!b || !b.start || !b.end) return total; const duration = timeToMinutes(b.end) - timeToMinutes(b.start); return total + Math.max(0, duration); }, 0); } /** * Berechnet die tatsächlich geleisteten Netto-Minuten. * @param {string} startTime z. B. "08:00" * @param {string} endTime z. B. "17:00" * @param {Array<{start: string, end: string}>} breaks Pausenzeiten * @returns {number} */ function computeWorkedMinutes(startTime, endTime, breaks) { const gross = timeToMinutes(endTime) - timeToMinutes(startTime); const totalBreak = computeTotalBreakMinutes(breaks); return gross - totalBreak; } /** Saldo (Über-/Minusstunden) eines einzelnen Tages in Minuten. */ function computeBalanceMinutes(workedMinutes, dateStr, settings) { const targetMinutes = isWorkDay(dateStr, settings.workDays) ? settings.targetHoursPerDay * 60 : 0; return workedMinutes - targetMinutes; } /** "2026-06-23" -> "Di, 23.06.2026" */ function formatDateDisplay(dateStr) { const date = new Date(`${dateStr}T00:00:00`); return new Intl.DateTimeFormat('de-DE', { weekday: 'short', day: '2-digit', month: '2-digit', year: 'numeric', }).format(date); } /** "2026-06" -> "Juni 2026" */ function formatMonthDisplay(yearMonth) { const date = new Date(`${yearMonth}-01T00:00:00`); return new Intl.DateTimeFormat('de-DE', { month: 'long', year: 'numeric' }).format(date); } module.exports = { WEEKDAY_NAMES, timeToMinutes, minutesToHM, formatBalance, isWorkDay, computeTotalBreakMinutes, computeWorkedMinutes, computeBalanceMinutes, formatDateDisplay, formatMonthDisplay, };