diff --git a/apps/cron/20260201-000000/lib/schedules.ts b/apps/cron/20260201-000000/lib/schedules.ts index a4b2618..63b43cd 100644 --- a/apps/cron/20260201-000000/lib/schedules.ts +++ b/apps/cron/20260201-000000/lib/schedules.ts @@ -4,6 +4,7 @@ export type Schedule = | "30 minutes" | "15 minutes" | "5 minutes" | "1 minute" | "30minutes" | "15minutes" | "5minutes" | "1minute" | 30 | 15 | 5 | 1 + | (string & {}) // time strings like "7am", "7:30pm", "14:00" export type CronJob = { id: string // "appname:filename" @@ -71,19 +72,48 @@ const SCHEDULE_MAP: Record = { '1minute': '* * * * *', } -export function toCronExpr(schedule: Schedule): string { - if (typeof schedule === 'number') { - return SCHEDULE_MAP[`${schedule}minutes`]! - } - return SCHEDULE_MAP[schedule]! -} - export function isValidSchedule(value: unknown): value is Schedule { if (typeof value === 'number') { return [1, 5, 15, 30].includes(value) } if (typeof value === 'string') { - return value in SCHEDULE_MAP + return value in SCHEDULE_MAP || parseTime(value) !== null } return false } + +function parseTime(s: string): { hour: number, minute: number } | null { + // 12h: "7am", "7pm", "7:30am", "7:30pm", "12am", "12:00pm" + const m12 = s.match(/^(\d{1,2})(?::(\d{2}))?\s*(am|pm)$/i) + if (m12) { + let hour = parseInt(m12[1]) + const minute = m12[2] ? parseInt(m12[2]) : 0 + const period = m12[3].toLowerCase() + if (hour < 1 || hour > 12 || minute > 59) return null + if (period === 'am' && hour === 12) hour = 0 + else if (period === 'pm' && hour !== 12) hour += 12 + return { hour, minute } + } + + // 24h: "14:00", "0:00", "23:59" + const m24 = s.match(/^(\d{1,2}):(\d{2})$/) + if (m24) { + const hour = parseInt(m24[1]) + const minute = parseInt(m24[2]) + if (hour > 23 || minute > 59) return null + return { hour, minute } + } + + return null +} + +export function toCronExpr(schedule: Schedule): string { + if (typeof schedule === 'number') { + return SCHEDULE_MAP[`${schedule}minutes`]! + } + if (schedule in SCHEDULE_MAP) { + return SCHEDULE_MAP[schedule]! + } + const time = parseTime(schedule)! + return `${time.minute} ${time.hour} * * *` +}