UNPKG

@atlaskit/datetime-picker

Version:

A date time picker allows the user to select an associated date and time.

156 lines • 5.33 kB
import { convertTo24hrTime } from './convert-to24hr-time'; import { isValid } from './is-valid'; import { removeSpacer } from './remove-spacer'; function assignToDate(time) { const dateTime = new Date(); dateTime.setHours(time.hour); dateTime.setMinutes(time.minute); // milliseconds is not supported dateTime.setSeconds(time.seconds || 0, 0); return dateTime; } function parseLegacyTime(time, allowCompactTime = false) { const trimmedTime = time.toString().trim(); const compactTime = allowCompactTime ? trimmedTime.match(/^\d{5}$/) : null; if (compactTime) { const normalizedTime = `0${compactTime[0]}`; const hour = Number(normalizedTime.slice(0, 2)); const minute = Number(normalizedTime.slice(2, 4)); const seconds = Number(normalizedTime.slice(4, 6)); if (minute <= 59 && seconds <= 59) { return assignToDate({ hour, minute, seconds }); } } if (/^\d{5}$/.test(trimmedTime)) { throw RangeError('invalid time format'); } if (!isValid(trimmedTime)) { throw RangeError('invalid time format'); } const time1 = removeSpacer(trimmedTime); const time2 = convertTo24hrTime(time1); if (!time2) { throw RangeError('invalid time format'); } return assignToDate({ ...time2, hour: time2.hour === 24 ? 0 : time2.hour }); } const escapeRegExp = value => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const normalizeDigits = (time, timeFormat) => Array.from(time, character => timeFormat.digits[character] || character).join(''); const isValidHourForCycle = (hour, hourCycle) => hourCycle === 'h11' ? hour <= 11 : hourCycle === 'h12' ? hour >= 1 && hour <= 12 : hour <= 24; function parseExactLocalizedTime(time, timeFormat) { if (!timeFormat.timeParts) { return undefined; } const dayPeriods = Object.entries(timeFormat.dayPeriods).filter(([, value]) => value); const groupTypes = []; const patternParts = timeFormat.timeParts.map(part => { if (part.type === 'hour' || part.type === 'minute' || part.type === 'second') { groupTypes.push(part.type); return part.type === 'hour' ? '(\\d{1,2})' : '(\\d{2})'; } if (part.type === 'dayPeriod') { if (dayPeriods.length === 0) { return null; } groupTypes.push('dayPeriod'); return `(${dayPeriods.map(([, value]) => escapeRegExp(value)).join('|')})`; } if (part.type === 'literal') { return escapeRegExp(part.value); } return null; }); if (patternParts.some(part => part === null)) { return undefined; } const match = time.match(new RegExp(`^${patternParts.join('')}$`, 'u')); if (!match) { return undefined; } const values = Object.fromEntries(groupTypes.map((type, index) => [type, match[index + 1]])); if (!values.hour || !values.minute) { return undefined; } const hour = Number(values.hour); const minute = Number(values.minute); const seconds = Number(values.second || '0'); if (minute > 59 || seconds > 59) { return null; } if (values.dayPeriod) { var _dayPeriods$find; const period = (_dayPeriods$find = dayPeriods.find(([, value]) => value === values.dayPeriod)) === null || _dayPeriods$find === void 0 ? void 0 : _dayPeriods$find[0]; if (!period || !isValidHourForCycle(hour, timeFormat.hourCycle)) { return null; } return assignToDate({ hour: period === 'pm' ? hour % 12 + 12 : hour % 12, minute, seconds }); } if (hour > 24) { return null; } return assignToDate({ hour: hour === 24 ? 0 : hour, minute, seconds }); } function parseLocalizedTime(normalizedTime, timeFormat) { const dayPeriods = Object.entries(timeFormat.dayPeriods).filter(([, value]) => value); const markers = dayPeriods.filter(([, value]) => new RegExp(escapeRegExp(value), 'u').test(normalizedTime)); if (markers.length === 0) { return undefined; } if (markers.length !== 1) { return null; } const [[period, marker]] = markers; const numericTime = normalizedTime.replace(new RegExp(escapeRegExp(marker), 'u'), '').trim(); const match = numericTime.match(/^(\d{1,2})(?:[:.](\d{2}))?(?:[:.](\d{2}))?$/); if (!match) { return null; } const [, hourValue, minuteValue = '0', secondValue = '0'] = match; const hour = Number(hourValue); const minute = Number(minuteValue); const seconds = Number(secondValue); if (!isValidHourForCycle(hour, timeFormat.hourCycle) || minute > 59 || seconds > 59) { return null; } return assignToDate({ hour: period === 'pm' ? hour % 12 + 12 : hour % 12, minute, seconds }); } export default function parseTime(time, timeFormat) { if (timeFormat) { const normalizedTime = normalizeDigits(time, timeFormat); const exactLocalizedTime = parseExactLocalizedTime(normalizedTime, timeFormat); if (exactLocalizedTime instanceof Date) { return exactLocalizedTime; } if (exactLocalizedTime === null) { throw RangeError('invalid time format'); } const localizedTime = parseLocalizedTime(normalizedTime, timeFormat); if (localizedTime instanceof Date) { return localizedTime; } if (localizedTime === null) { throw RangeError('invalid time format'); } return parseLegacyTime(normalizedTime, true); } return parseLegacyTime(time); }