// Gleiche Logik wie helpers/utils.js formatHoursMin – für Browser (Dashboard, EJS-Seiten). // Wird global als window.formatHoursMin bereitgestellt. (function () { function formatHoursMin(decimalHours) { if (decimalHours == null || !Number.isFinite(Number(decimalHours))) return '0h 0min'; var n = Number(decimalHours); var sign = n < 0 ? -1 : 1; var absVal = Math.abs(n); var h = Math.floor(absVal); var min = Math.round((absVal - h) * 60); if (min >= 60) { h += 1; min = 0; } var prefix = sign < 0 ? '-' : ''; return prefix + h + 'h ' + min + 'min'; } /** Dezimalstunden in h:mm (z. B. 1.5 -> "1:30", -0.75 -> "-0:45") */ function decimalHoursToHhMm(decimalHours) { if (decimalHours == null || !Number.isFinite(Number(decimalHours))) return '0:00'; var n = Number(decimalHours); var sign = n < 0 ? -1 : 1; var absVal = Math.abs(n); var h = Math.floor(absVal); var min = Math.round((absVal - h) * 60); if (min >= 60) { h += 1; min = 0; } var prefix = sign < 0 ? '-' : ''; return prefix + h + ':' + String(min).padStart(2, '0'); } /** * Parst h:mm oder Xh Ymin zu Dezimalstunden. * Beispiele: "1:30" -> 1.5, "-0:45" -> -0.75, "1h 30min" -> 1.5. * @returns {number|null} Dezimalstunden oder null bei ungültiger Eingabe */ function parseHoursMin(str) { if (str == null) return null; var s = String(str).trim(); if (s === '') return 0; var sign = 1; if (s.charAt(0) === '-') { sign = -1; s = s.slice(1).trim(); } else if (s.charAt(0) === '+') { s = s.slice(1).trim(); } // h:mm oder h:mm:ss var colonMatch = s.match(/^(\d+):(\d{1,2})(?::(\d{1,2}))?$/); if (colonMatch) { var hours = parseInt(colonMatch[1], 10); var minutes = parseInt(colonMatch[2], 10); if (minutes >= 60) return null; var sec = colonMatch[3] != null ? parseInt(colonMatch[3], 10) : 0; if (sec >= 60) return null; var decimal = hours + minutes / 60 + sec / 3600; return sign * decimal; } // Xh Ymin (optional Leerzeichen) var hmMatch = s.match(/^(\d+)\s*h\s*(\d{1,2})?\s*min$/i); if (hmMatch) { var h = parseInt(hmMatch[1], 10); var m = (hmMatch[2] != null) ? parseInt(hmMatch[2], 10) : 0; if (m >= 60) return null; return sign * (h + m / 60); } // Nur Zahl (Dezimalstunden) zulassen als Fallback var num = parseFloat(s.replace(',', '.')); if (!Number.isFinite(num)) return null; return sign * num; } window.formatHoursMin = formatHoursMin; window.decimalHoursToHhMm = decimalHoursToHhMm; window.parseHoursMin = parseHoursMin; })();