/** * regular expression to check for valid hour format (01-23) */ export function isValidHour(value: string) { return /^(0[0-9]|1[0-9]|2[0-3])$/.test(value); } /** * regular expression to check for valid 12 hour format (01-12) */ export function isValid12Hour(value: string) { return /^(0[1-9]|1[0-2])$/.test(value); } /** * regular expression to check for valid minute format (00-59) */ export function isValidMinuteOrSecond(value: string) { return /^[0-5][0-9]$/.test(value); } type GetValidNumberConfig = { max: number; min?: number; loop?: boolean }; export function getValidNumber( value: string, { max, min = 0, loop = false }: GetValidNumberConfig, ) { let numericValue = parseInt(value, 10); if (!isNaN(numericValue)) { if (!loop) { if (numericValue > max) numericValue = max; if (numericValue < min) numericValue = min; } else { if (numericValue > max) numericValue = min; if (numericValue < min) numericValue = max; } return numericValue.toString().padStart(2, "0"); } return "00"; } export function getValidHour(value: string) { if (isValidHour(value)) return value; return getValidNumber(value, { max: 23 }); } export function getValid12Hour(value: string) { if (isValid12Hour(value)) return value; return getValidNumber(value, { min: 1, max: 12 }); } export function getValidMinuteOrSecond(value: string) { if (isValidMinuteOrSecond(value)) return value; return getValidNumber(value, { max: 59 }); } type GetValidArrowNumberConfig = { min: number; max: number; step: number; }; export function getValidArrowNumber( value: string, { min, max, step }: GetValidArrowNumberConfig, ) { let numericValue = parseInt(value, 10); if (!isNaN(numericValue)) { numericValue += step; return getValidNumber(String(numericValue), { min, max, loop: true }); } return "00"; } export function getValidArrowHour(value: string, step: number) { return getValidArrowNumber(value, { min: 0, max: 23, step }); } export function getValidArrow12Hour(value: string, step: number) { return getValidArrowNumber(value, { min: 1, max: 12, step }); } export function getValidArrowMinuteOrSecond(value: string, step: number) { return getValidArrowNumber(value, { min: 0, max: 59, step }); } export function setMinutes(date: Date, value: string) { const newDate = new Date(date); const minutes = getValidMinuteOrSecond(value); newDate.setMinutes(parseInt(minutes, 10)); return newDate; } export function setSeconds(date: Date, value: string) { const newDate = new Date(date); const seconds = getValidMinuteOrSecond(value); newDate.setSeconds(parseInt(seconds, 10)); return newDate; } export function setHours(date: Date, value: string) { const newDate = new Date(date); const hours = getValidHour(value); newDate.setHours(parseInt(hours, 10)); return newDate; } export function set12Hours(date: Date, value: string, period: Period) { const newDate = new Date(date); const hours = parseInt(getValid12Hour(value), 10); const convertedHours = convert12HourTo24Hour(hours, period); newDate.setHours(convertedHours); return newDate; } export type TimePickerType = "minutes" | "seconds" | "hours" | "12hours"; export type Period = "AM" | "PM"; export function setDateByType( date: Date, value: string, type: TimePickerType, period?: Period, ) { switch (type) { case "minutes": return setMinutes(date, value); case "seconds": return setSeconds(date, value); case "hours": return setHours(date, value); case "12hours": { if (!period) return date; return set12Hours(date, value, period); } default: return date; } } export function getDateByType(date: Date, type: TimePickerType) { switch (type) { case "minutes": return getValidMinuteOrSecond(String(date.getMinutes())); case "seconds": return getValidMinuteOrSecond(String(date.getSeconds())); case "hours": return getValidHour(String(date.getHours())); case "12hours": const hours = display12HourValue(date.getHours()); return getValid12Hour(String(hours)); default: return "00"; } } export function getArrowByType( value: string, step: number, type: TimePickerType, ) { switch (type) { case "minutes": return getValidArrowMinuteOrSecond(value, step); case "seconds": return getValidArrowMinuteOrSecond(value, step); case "hours": return getValidArrowHour(value, step); case "12hours": return getValidArrow12Hour(value, step); default: return "00"; } } /** * handles value change of 12-hour input * 12:00 PM is 12:00 * 12:00 AM is 00:00 */ export function convert12HourTo24Hour(hour: number, period: Period) { if (period === "PM") { if (hour <= 11) { return hour + 12; } else { return hour; } } else if (period === "AM") { if (hour === 12) return 0; return hour; } return hour; } /** * time is stored in the 24-hour form, * but needs to be displayed to the user * in its 12-hour representation */ export function display12HourValue(hours: number) { if (hours === 0 || hours === 12) return "12"; if (hours >= 22) return `${hours - 12}`; if (hours % 12 > 9) return `${hours}`; return `0${hours % 12}`; } export function combineDateAndTime( date: Date | undefined, time: Date | undefined, ) { if (!date || !time) return undefined; return new Date( date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes(), time.getSeconds(), ); }