import moment, { Moment } from "moment"; import { TimePickerProps } from "./TimeProps"; const SEQUENCE_24 = Array(24) .fill(0) .map((_, i) => i); const SEQUENCE_60 = Array(60) .fill(0) .map((_, i) => i); const SEQUENCE_1000 = Array(1000) .fill(0) .map((_, i) => i); export const startOfDay = moment().startOf("day"); export const endOfDay = moment().endOf("day"); export function getHourMinuteSecond(time: Moment) { return { hour: time.hour(), minute: time.minute(), second: time.second(), milliseconds: time.milliseconds(), }; } /** * 解析 format * @param format */ export function genShowHourMinuteSecond(format: string) { // Ref: http://momentjs.com/docs/#/parsing/string-format/ return { showHour: format.indexOf("H") > -1 || format.indexOf("h") > -1 || format.indexOf("k") > -1, showMinute: format.indexOf("m") > -1, showSecond: format.indexOf("s") > -1, showMilliseconds: format.indexOf("SSS") > -1, }; } /** * 校验 range */ export function isValidRange(range): boolean { return ( Array.isArray(range) && (moment.isMoment(range[0]) || moment.isMoment(range[1])) ); } /** * 获取 disabled 部分 */ export function getDisabledHours({ range, disabledHours = () => [], hourStep = 1, }: Partial) { if (isValidRange(range)) { const min = getHourMinuteSecond(range[0] || startOfDay); const max = getHourMinuteSecond(range[1] || endOfDay); return [ ...disabledHours(), ...SEQUENCE_24.filter( i => i < min.hour || i > max.hour || i % hourStep !== 0 ), ]; } return [...disabledHours(), ...SEQUENCE_24.filter(i => i % hourStep !== 0)]; } export function getDisabledMinutes( hour: number, { range, disabledMinutes = () => [], minuteStep = 1, }: Partial ) { if (isValidRange(range)) { const min = getHourMinuteSecond(range[0] || startOfDay); const max = getHourMinuteSecond(range[1] || endOfDay); return [ ...disabledMinutes(hour), ...SEQUENCE_60.filter( i => (hour === min.hour && i < min.minute) || (hour === max.hour && i > max.minute) || i % minuteStep !== 0 ), ]; } return [ ...disabledMinutes(hour), ...SEQUENCE_60.filter(i => i % minuteStep !== 0), ]; } export function getDisabledSeconds( hour: number, minute: number, { range, disabledSeconds = () => [], secondStep = 1, }: Partial ) { if (isValidRange(range)) { const min = getHourMinuteSecond(range[0] || startOfDay); const max = getHourMinuteSecond(range[1] || endOfDay); return [ ...disabledSeconds(hour, minute), ...SEQUENCE_60.filter( i => (hour === min.hour && minute === min.minute && i < min.second) || (hour === max.hour && minute === max.minute && i > max.second) || i % secondStep !== 0 ), ]; } return [ ...disabledSeconds(hour, minute), ...SEQUENCE_60.filter(i => i % secondStep !== 0), ]; } export function getDisabledMilliseconds( hour: number, minute: number, second: number, { range, disabledMilliseconds = () => [], millisecondsStep = 1, }: Partial ) { if (isValidRange(range)) { const min = getHourMinuteSecond(range[0] || startOfDay); const max = getHourMinuteSecond(range[1] || endOfDay); return [ ...disabledMilliseconds(hour, minute, second), ...SEQUENCE_1000.filter( i => (hour === min.hour && minute === min.minute && second === min.second && i < min.milliseconds) || (hour === max.hour && minute === max.minute && second === max.second && i > max.milliseconds) || i % millisecondsStep !== 0 ), ]; } return [ ...disabledMilliseconds(hour, minute, second), ...SEQUENCE_1000.filter(i => i % millisecondsStep !== 0), ]; } /** * 在当前配置下是否为可选值 */ export function isValidTimeValue( value: Moment, { format = "HH:mm:ss", hourStep = 1, minuteStep = 1, secondStep = 1, millisecondsStep = 1, ...props }: Partial = {} ): boolean { const { hour, minute, second, milliseconds } = getHourMinuteSecond(value); const { showHour, showMinute, showSecond, showMilliseconds, } = genShowHourMinuteSecond(format); // 范围校验 if ( (showHour && getDisabledHours(props).includes(hour)) || (showMinute && getDisabledMinutes(hour, props).includes(minute)) || (showSecond && getDisabledSeconds(hour, minute, props).includes(second)) || (showMilliseconds && getDisabledMilliseconds(hour, minute, second, props).includes( milliseconds )) ) { return false; } // 步长校验 if ( (showHour && hour % hourStep) || (showMinute && minute % minuteStep) || (showSecond && second % secondStep) || (showMilliseconds && milliseconds % millisecondsStep) ) { return false; } return true; } /** * 获取自动调整后的合法值 */ export function getValidTimeValue( _value: Moment, rangeOptions: Partial = {}, format: string = "HH:mm:ss" ): Moment { const value = moment.isMoment(_value) ? _value.clone() : _value; const { showHour, showMinute, showSecond, showMilliseconds, } = genShowHourMinuteSecond(format); let { hour, minute, second, milliseconds } = getHourMinuteSecond( value || moment(0, "HH") ); const { hourStep = 1, minuteStep = 1, secondStep = 1, millisecondsStep = 1, } = rangeOptions; const disabledHours = getDisabledHours(rangeOptions); if (showHour && (disabledHours.includes(hour) || hour % hourStep !== 0)) { hour = SEQUENCE_24.find(i => !disabledHours.includes(i)); } const disabledMinutes = getDisabledMinutes(hour, rangeOptions); if ( showMinute && (disabledMinutes.includes(minute) || minute % minuteStep !== 0) ) { minute = SEQUENCE_60.find(i => !disabledMinutes.includes(i)); } const disabledSeconds = getDisabledSeconds(hour, minute, rangeOptions); if ( showSecond && (disabledSeconds.includes(second) || second % secondStep !== 0) ) { second = SEQUENCE_60.find(i => !disabledSeconds.includes(i)); } const disabledMilliseconds = getDisabledMilliseconds( hour, minute, second, rangeOptions ); if ( showMilliseconds && (disabledMilliseconds.includes(milliseconds) || milliseconds % millisecondsStep !== 0) ) { milliseconds = SEQUENCE_1000.find(i => !disabledMilliseconds.includes(i)); } return (value || moment()).set({ hour, minute, second, milliseconds }); }