- Docker infrastructure (Dockerfile, docker-compose.yml, genieacs-sim) - AdonisJS v7 app with Inertia.js + Vue 3 - MongoDB integration - CWMP/TR-069 state machine engine - Configuration engine with compliance tracking - Branding: ADAM ACS (favicon, navbar, locales) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
import type { ScheduleWindow } from '../domain/configuration/configuration.js'
|
|
|
|
/**
|
|
* Checks if the current time (or provided time) falls within the schedule window.
|
|
* Returns true if no schedule is defined (no restriction).
|
|
*
|
|
* Handles:
|
|
* - IANA timezone conversion (uses the timezone to get local hour and day)
|
|
* - Midnight-spanning windows (startHour > endHour means spans midnight)
|
|
* - Day-of-week filtering (daysOfWeek array, 0=Sunday)
|
|
*/
|
|
export function isWithinSchedule(schedule: ScheduleWindow | undefined, now?: Date): boolean {
|
|
if (!schedule) {
|
|
return true
|
|
}
|
|
|
|
const currentTime = now ?? new Date()
|
|
|
|
// Get the local hour and day in the schedule's timezone
|
|
const localParts = getLocalTimeParts(currentTime, schedule.timezone)
|
|
const localHour = localParts.hour
|
|
const localDay = localParts.dayOfWeek // 0=Sunday
|
|
|
|
// Check day-of-week filter
|
|
if (schedule.daysOfWeek.length > 0 && !schedule.daysOfWeek.includes(localDay)) {
|
|
return false
|
|
}
|
|
|
|
// Check time window
|
|
const { startHour, endHour } = schedule
|
|
|
|
if (startHour <= endHour) {
|
|
// Normal window (e.g., 2-6 means 02:00 to 06:00)
|
|
return localHour >= startHour && localHour < endHour
|
|
} else {
|
|
// Midnight-spanning window (e.g., 22-6 means 22:00 to 06:00 next day)
|
|
return localHour >= startHour || localHour < endHour
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the local hour and day-of-week for a given Date in a specific IANA timezone.
|
|
*/
|
|
function getLocalTimeParts(
|
|
date: Date,
|
|
timezone: string
|
|
): { hour: number; dayOfWeek: number } {
|
|
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
timeZone: timezone,
|
|
hour: 'numeric',
|
|
weekday: 'short',
|
|
hour12: false,
|
|
})
|
|
|
|
const parts = formatter.formatToParts(date)
|
|
|
|
let hour = 0
|
|
let dayOfWeek = 0
|
|
|
|
for (const part of parts) {
|
|
if (part.type === 'hour') {
|
|
// Intl may return "24" for midnight in some locales, normalize to 0
|
|
hour = Number.parseInt(part.value, 10) % 24
|
|
}
|
|
if (part.type === 'weekday') {
|
|
dayOfWeek = weekdayToNumber(part.value)
|
|
}
|
|
}
|
|
|
|
return { hour, dayOfWeek }
|
|
}
|
|
|
|
/**
|
|
* Converts a short weekday name (from Intl) to a number (0=Sunday).
|
|
*/
|
|
function weekdayToNumber(weekday: string): number {
|
|
const map: Record<string, number> = {
|
|
Sun: 0,
|
|
Mon: 1,
|
|
Tue: 2,
|
|
Wed: 3,
|
|
Thu: 4,
|
|
Fri: 5,
|
|
Sat: 6,
|
|
}
|
|
return map[weekday] ?? 0
|
|
}
|