80 lines
2.6 KiB
JavaScript
80 lines
2.6 KiB
JavaScript
// 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;
|
||
})();
|