/** * Parse `BARE_OS_REPLICATION_SYNC_WINDOWS` (UTC, `HH:MM-HH:MM` ranges, comma-separated). * @param {Record} env * @returns {{ active: boolean, windows: string[], nowUtc: string, note?: string }} */ export function computeReplicationSyncWindow(env) { const raw = String(env.BARE_OS_REPLICATION_SYNC_WINDOWS || '').trim() const now = new Date() const pad = (n) => (n < 10 ? '0' : '') + n const nowUtc = `${pad(now.getUTCHours())}:${pad(now.getUTCMinutes())}` if (!raw) { return { active: true, windows: [], nowUtc, note: 'no windows; replication always allowed' } } const parts = raw .split(',') .map((s) => s.trim()) .filter(Boolean) /** @type {string[]} */ const windows = [] let active = false const toMin = (h, m) => h * 60 + m const cur = toMin(now.getUTCHours(), now.getUTCMinutes()) for (const p of parts) { const m = p.match(/^(\d{1,2}):(\d{2})\s*-\s*(\d{1,2}):(\d{2})$/) if (!m) continue const a = toMin(Number(m[1]), Number(m[2])) const b = toMin(Number(m[3]), Number(m[4])) windows.push(p) if (a <= b) { if (cur >= a && cur <= b) active = true } else { if (cur >= a || cur <= b) active = true } } if (windows.length === 0) { return { active: true, windows: [], nowUtc, note: 'no valid windows parsed; default allow' } } return { active, windows, nowUtc } }