@kwiz/common
Version:
KWIZ common utilities and helpers for M365 platform
132 lines (119 loc) • 4.85 kB
text/typescript
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)}`;
}