From 404c1d27dcacbffb68262b11b552e4a233b521e2 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 30 Jun 2026 20:09:08 +0000 Subject: [PATCH] Initial --- src/utils/time.js | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/utils/time.js diff --git a/src/utils/time.js b/src/utils/time.js new file mode 100644 index 0000000..c29a1a4 --- /dev/null +++ b/src/utils/time.js @@ -0,0 +1,71 @@ +// 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); +} + +/** Berechnet die tatsächlich geleisteten Minuten abzüglich Pause. */ +function computeWorkedMinutes(startTime, endTime, breakMinutes) { + return timeToMinutes(endTime) - timeToMinutes(startTime) - Number(breakMinutes || 0); +} + +/** 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, + computeWorkedMinutes, + computeBalanceMinutes, + formatDateDisplay, + formatMonthDisplay, +};