Source: js/chart-time-utils.js

// chart-time-utils.js
// Zeit-Parsing, Formatierung, Fenster-Berechnung

/**
 * Konvertiert Zeitstempel zu Millisekunden (UTC-aware)
 * @param {number|string|null} ts - Zeitstempel (Sekunden, Millisekunden oder ISO-String)
 * @returns {number|null} Millisekunden seit Epoch oder null
 */
export function toMs(ts) {
  if (ts == null) return null;
  if (typeof ts === 'number') return ts > 2_000_000_000 ? ts : ts * 1000;
  const s = String(ts).trim();
  // Nur Leerzeichen → 'T' ersetzen, aber 'Z' NICHT entfernen (UTC beibehalten)
  const iso = s.includes(' ') ? s.replace(' ', 'T') : s;
  const d = new Date(iso);
  return Number.isFinite(+d) ? +d : null;
}

export const parseLocalMs = toMs;

/**
 * Formatiert Zeitstempel als HH:MM
 * @param {number} ms - Millisekunden seit Epoch
 * @param {string} [locale='de-AT'] - Locale-String
 * @param {string} [tz] - Zeitzone (optional)
 * @returns {string} Formatierte Zeit (z.B. "14:30")
 */
export function fmtHM(ms, locale = 'de-AT', tz = undefined) {
  if (!Number.isFinite(ms)) return '–:–';
  return new Date(ms).toLocaleString(locale, {
    hour: '2-digit',
    minute: '2-digit',
    timeZone: tz,
  });
}

/**
 * Formatiert Zeitstempel als DD.MM.
 * @param {number} ms - Millisekunden seit Epoch
 * @param {string} [locale='de-AT'] - Locale-String
 * @returns {string} Formatiertes Datum (z.B. "28.10.")
 */
export function fmtDM(ms, locale = 'de-AT') {
  if (!Number.isFinite(ms)) return '–';
  return new Date(ms).toLocaleDateString(locale, { day: '2-digit', month: '2-digit' });
}

/**
 * Gibt Start der Woche (Montag 00:00) zurück
 * @param {number} ms - Millisekunden seit Epoch
 * @returns {number} Wochenstart in Millisekunden
 */
export function startOfWeek(ms) {
  const d = new Date(ms);
  const dow = (d.getDay() + 6) % 7; // Mo=0
  d.setHours(0, 0, 0, 0);
  d.setDate(d.getDate() - dow);
  return +d;
}

/**
 * Berechnet gleitendes Zeitfenster für Modus (auto/day/week/month)
 * @param {string} mode - Chart-Modus ('auto', 'day', 'week', 'month')
 * @param {number} anchorMs - Anker-Zeitpunkt in Millisekunden
 * @returns {{start: number, end: number}} Zeitfenster {start, end} in Millisekunden
 */
export function windowFor(mode, anchorMs) {
  const DAY = 24 * 3600 * 1000;
  const WEEK = 7 * DAY;
  if (mode === 'week') return { start: anchorMs - WEEK, end: anchorMs };
  if (mode === 'month') return { start: anchorMs - 5 * WEEK, end: anchorMs };
  // 'auto' | 'day'
  return { start: anchorMs - DAY, end: anchorMs };
}