import type { RoutineEventBlock } from "@rakazo/contracts"; import { routineScheduleShape } from "@rakazo/core"; import { dateLocaleForUi, t } from "./i18n"; /** 2024-01-07 is a Sunday, so day n of that week has weekday n. */ const weekdayName = (weekday: number, locale: string) => new Intl.DateTimeFormat(locale, { weekday: "long", timeZone: "UTC" }).format( new Date(Date.UTC(2024, 0, 7 + weekday)), ); const clock = (hour: number, minute: number, locale: string) => new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "2-digit", timeZone: "UTC" }).format( new Date(Date.UTC(2024, 0, 1, hour, minute)), ); /** When a routine runs, in a few words of the active locale. */ export function routineLineSchedule( block: Pick, locale = dateLocaleForUi(), ): string { const shape = routineScheduleShape(block.crons); switch (shape.kind) { case "hourly": return t("Every hour"); case "minutes": return t("Every {count} min", { count: shape.every }); case "hours": return t("Every {count} h", { count: shape.every }); case "daily": return t("Daily, {time}", { time: clock(shape.hour, shape.minute, locale) }); case "weekdays": return t("Weekdays, {time}", { time: clock(shape.hour, shape.minute, locale) }); case "weekly": return t("Every {day}, {time}", { day: weekdayName(shape.weekday, locale), time: clock(shape.hour, shape.minute, locale), }); case "monthly": return t("Monthly on day {day}, {time}", { day: shape.day, time: clock(shape.hour, shape.minute, locale), }); default: { if (!block.nextRunAt) return ""; const date = new Intl.DateTimeFormat(locale, { weekday: "short", day: "numeric", month: "short", hour: "numeric", minute: "2-digit", timeZone: block.timezone, }).format(new Date(block.nextRunAt)); return shape.kind === "once" ? date : t("Next {date}", { date }); } } }