UNPKG

@kwiz/common

Version:

KWIZ common utilities and helpers for M365 platform

132 lines (119 loc) 4.85 kB
import { firstOrNull, sortNumberArrayAsc } from "../collections.base"; import { cloneDate } from "../date"; import { padLeft } from "../strings"; import { isNotEmptyArray, isNullOrUndefined } from "../typecheckers"; export type hourlyInterval = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; export type hours = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23; export type days = 0 | 1 | 2 | 3 | 4 | 5 | 6; export enum ScheduleTypes { hourly = "hourly", daily = "daily", weekly = "weekly" } export const ScheduleTypesDefinitions: { [Name: string]: { title: string, value: ScheduleTypes }; } = { weekly: { value: ScheduleTypes.weekly, title: "Run on specific days, at specific times" }, daily: { value: ScheduleTypes.daily, title: "Run every day, at specific times" }, hourly: { value: ScheduleTypes.hourly, title: "Run every few hours" } }; export interface IScheduleHourly { ScheduleType: ScheduleTypes.hourly, /** run every x number of hours */ interval: hourlyInterval; } export interface IScheduleDaily { ScheduleType: ScheduleTypes.daily, /** run every day, at these hours */ hours: hours[]; } export interface IScheduleWeekly { ScheduleType: ScheduleTypes.weekly, /** run in the following days */ days: days[]; /** run at these hours */ hours: hours[]; } export type TypeSchedule = IScheduleHourly | IScheduleDaily | IScheduleWeekly; export const defaultWeeklySchedule: IScheduleWeekly = { ScheduleType: ScheduleTypes.weekly, days: [1, 2, 3, 4, 5], hours: [0] }; export const defaultDailySchedule: IScheduleDaily = { ScheduleType: ScheduleTypes.daily, hours: [0, 12] }; export const defaultHourlySchedule: IScheduleHourly = { ScheduleType: ScheduleTypes.hourly, interval: 4 }; export function isValidSchedule(schedule: TypeSchedule) { if (isNullOrUndefined(schedule)) return false; if (schedule.ScheduleType === ScheduleTypes.hourly) return schedule.interval > 0 && schedule.interval <= 12; else if (schedule.ScheduleType === ScheduleTypes.daily) { return isNotEmptyArray(schedule.hours) && schedule.hours.every(h => h >= 0 && h <= 23); } else if (schedule.ScheduleType === ScheduleTypes.weekly) { return isNotEmptyArray(schedule.hours) && schedule.hours.every(h => h >= 0 && h <= 23) && isNotEmptyArray(schedule.days) && schedule.days.every(d => d >= 0 && d <= 6); } else return false; } /** returns a yyyyMMddHH for the next time this schedule needs to run after the currentDate */ export function getNextUTC(currentDate: Date, schedule: TypeSchedule): string { if (!isValidSchedule(schedule)) return "9999999999"; currentDate = cloneDate(currentDate); let date = currentDate.getUTCDate(); let hour = currentDate.getUTCHours(); let day = currentDate.getUTCDay() as days; //adjust date based on selected schedule if (schedule.ScheduleType === ScheduleTypes.hourly) { hour += schedule.interval; currentDate.setUTCHours(hour); } else if (schedule.ScheduleType === ScheduleTypes.daily) { //get current hour, see if the next run is today or tomorrow let sortedHours = schedule.hours.sort(sortNumberArrayAsc); let nextHour = firstOrNull(sortedHours.filter(h => h > hour)); if (nextHour !== null) { currentDate.setUTCHours(nextHour); } else { //tomorrow at the first scheduled hour currentDate.setUTCHours(sortedHours[0]); currentDate.setUTCDate(date + 1); } } else { //implement weekly let sortedDays = schedule.days.sort(sortNumberArrayAsc); let sortedHours = schedule.hours.sort(sortNumberArrayAsc); let nextHour = firstOrNull(sortedHours.filter(h => h > hour)); let nextDay = firstOrNull(sortedDays.filter(h => h > day)); if (sortedDays.includes(day) && nextHour !== null)//today is allowed { currentDate.setUTCHours(nextHour); } else//move to next allowed day, at first hour allowed { let daysToAdd = nextDay === null ? 7 - day + sortedDays[0] : nextDay - day; currentDate.setUTCHours(sortedHours[0]); currentDate.setUTCDate(date + daysToAdd); } } return getUTCDateMarker(currentDate); } export function getUTCDateMarker(date: Date) { return `${date.getUTCFullYear()}${padLeft(date.getUTCMonth() + 1, 2)}${padLeft(date.getUTCDate(), 2)}${padLeft(date.getUTCHours(), 2)}`; }