import dayjs, { type Dayjs } from "dayjs"; import customParseFormat from "dayjs/plugin/customParseFormat"; dayjs.extend(customParseFormat); const CLOCK_DATE = "2000-01-01"; const CLOCK_TIME_FORMATS = [ "YYYY-MM-DD H:m", "YYYY-MM-DD H:mm", "YYYY-MM-DD HH:m", "YYYY-MM-DD HH:mm", ]; /** Parse a timetable clock value, accepting legacy and zero-padded forms. */ export const parseClockTime = (time: string): Dayjs | null => { const value = time?.trim(); if (!value) return null; const parsed = dayjs(`${CLOCK_DATE} ${value}`, CLOCK_TIME_FORMATS, true); return parsed.isValid() ? parsed : null; }; /** Normalize a timetable clock value to HH:mm, preserving invalid input. */ export const normalizeTime = (time: string) => parseClockTime(time)?.format("HH:mm") ?? time; /** Set a clock value on a base date without applying service-day rollover. */ export const setClockTime = (base: Dayjs, time: string, delayMinutes = 0) => { const parsed = parseClockTime(time); if (!parsed) return null; return base .clone() .hour(parsed.hour()) .minute(parsed.minute()) .second(0) .millisecond(0) .add(delayMinutes, "minute"); }; /** Set a timetable value on a base date, treating 00:00-03:59 as service-day late night. */ export const setServiceTime = (base: Dayjs, time: string, delayMinutes = 0) => { const parsed = parseClockTime(time); if (!parsed) return null; return base .clone() .hour(parsed.hour() < 4 ? parsed.hour() + 24 : parsed.hour()) .minute(parsed.minute()) .second(0) .millisecond(0) .add(delayMinutes, "minute"); }; export const getServiceTimeDifference = ( base: Dayjs, time: string, delayMinutes = 0 ) => { const parsed = parseClockTime(time); const target = setServiceTime(base, time, delayMinutes); if (!parsed || !target) return null; const adjustedTarget = base.hour() < 4 && parsed.hour() < 4 ? target.subtract(1, "day") : target; return adjustedTarget.diff(base, "minute"); }; export const getServiceMinute = (time: string) => { const parsed = parseClockTime(time); if (!parsed) return null; return (parsed.hour() < 4 ? parsed.hour() + 24 : parsed.hour()) * 60 + parsed.minute(); };