UNPKG

igniteui-webcomponents

Version:

Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.

599 lines 22 kB
import { parseISODate } from '../calendar/helpers.js'; import { MaskParser } from '../mask-input/mask-parser.js'; export var FormatDesc; (function (FormatDesc) { FormatDesc["Numeric"] = "numeric"; FormatDesc["TwoDigits"] = "2-digit"; })(FormatDesc || (FormatDesc = {})); export var DateParts; (function (DateParts) { DateParts["Day"] = "day"; DateParts["Month"] = "month"; DateParts["Year"] = "year"; DateParts["Date"] = "date"; DateParts["Hours"] = "hours"; DateParts["Minutes"] = "minutes"; DateParts["Seconds"] = "seconds"; DateParts["AmPm"] = "amPm"; DateParts["Literal"] = "literal"; })(DateParts || (DateParts = {})); export var DatePart; (function (DatePart) { DatePart["Month"] = "month"; DatePart["Year"] = "year"; DatePart["Date"] = "date"; DatePart["Hours"] = "hours"; DatePart["Minutes"] = "minutes"; DatePart["Seconds"] = "seconds"; DatePart["AmPm"] = "amPm"; })(DatePart || (DatePart = {})); function isDate(value) { return value instanceof Date; } export class DateTimeUtil { static parseValueFromMask(inputData, dateTimeParts, promptChar) { const parts = {}; dateTimeParts.forEach((dp) => { let value = Number.parseInt(DateTimeUtil.getCleanVal(inputData, dp, promptChar), 10); if (!value) { value = dp.type === DateParts.Date || dp.type === DateParts.Month ? 1 : 0; } parts[dp.type] = value; }); parts[DateParts.Month] -= 1; if (parts[DateParts.Month] < 0 || 11 < parts[DateParts.Month]) { return null; } if (parts[DateParts.Year] < 50) { parts[DateParts.Year] += 2000; } if (parts[DateParts.Date] > DateTimeUtil.daysInMonth(parts[DateParts.Year], parts[DateParts.Month])) { return null; } if (parts[DateParts.Hours] > 23 || parts[DateParts.Minutes] > 59 || parts[DateParts.Seconds] > 59) { return null; } const amPm = dateTimeParts.find((p) => p.type === DateParts.AmPm); if (amPm) { parts[DateParts.Hours] %= 12; } if (amPm && DateTimeUtil.getCleanVal(inputData, amPm, promptChar).toLowerCase() === 'pm') { parts[DateParts.Hours] += 12; } return new Date(parts[DateParts.Year] || 2000, parts[DateParts.Month] || 0, parts[DateParts.Date] || 1, parts[DateParts.Hours] || 0, parts[DateParts.Minutes] || 0, parts[DateParts.Seconds] || 0); } static getDefaultMask(locale) { const parts = DateTimeUtil.getDefaultLocaleMask(locale || DateTimeUtil.DEFAULT_LOCALE); if (parts !== undefined) { parts.forEach((p) => { if (p.type !== DateParts.Year && p.type !== DateTimeUtil.SEPARATOR) { p.formatType = FormatDesc.TwoDigits; } }); return DateTimeUtil.getMask(parts); } return ''; } static parseDateTimeFormat(mask, locale = DateTimeUtil.DEFAULT_LOCALE, noLeadingZero = false) { const format = mask || DateTimeUtil.getDefaultMask(locale); const dateTimeParts = []; const formatArray = Array.from(format); let currentPart = null; let position = 0; for (let i = 0; i < formatArray.length; i++, position++) { const type = DateTimeUtil.determineDatePart(formatArray[i]); if (currentPart) { if (currentPart.type === type) { currentPart.format += formatArray[i]; if (i < formatArray.length - 1) { continue; } } DateTimeUtil.addCurrentPart(currentPart, dateTimeParts, noLeadingZero); position = currentPart.end; } currentPart = { start: position, end: position + formatArray[i].length, type, format: formatArray[i], }; } if (!dateTimeParts.filter((p) => p.format.includes(currentPart.format)) .length) { DateTimeUtil.addCurrentPart(currentPart, dateTimeParts, noLeadingZero); } const yearPart = dateTimeParts.filter((p) => p.type === DateParts.Year)[0]; if (yearPart && yearPart.format !== 'yy') { yearPart.end += 4 - yearPart.format.length; yearPart.format = 'yyyy'; } return dateTimeParts; } static parseIsoDate(value) { return parseISODate(value); } static isValidDate(value) { if (isDate(value)) { return !Number.isNaN(value.getTime()); } return false; } static formatDate(value, locale, format, noLeadingZero = false) { const options = {}; let formattedDate = ''; switch (format) { case 'short': case 'long': case 'medium': case 'full': options.dateStyle = format; options.timeStyle = format; break; case 'shortDate': case 'longDate': case 'mediumDate': case 'fullDate': options.dateStyle = format.toLowerCase().split('date')[0]; break; case 'shortTime': case 'longTime': case 'mediumTime': case 'fullTime': options.timeStyle = format.toLowerCase().split('time')[0]; break; default: return DateTimeUtil.setDisplayFormatOptions(value, format, locale, noLeadingZero); } let formatter; try { formatter = new Intl.DateTimeFormat(locale, options); } catch { formatter = new Intl.DateTimeFormat(DateTimeUtil.DEFAULT_LOCALE, options); } formattedDate = formatter.format(value); return formattedDate; } static getPartValue(datePartInfo, partLength, _dateValue) { let maskedValue; const datePart = datePartInfo.type; switch (datePart) { case DateParts.Date: maskedValue = _dateValue.getDate(); break; case DateParts.Month: maskedValue = _dateValue.getMonth() + 1; break; case DateParts.Year: if (partLength === 2) { maskedValue = DateTimeUtil.prependValue(Number.parseInt(_dateValue.getFullYear().toString().slice(-2), 10), partLength, '0'); } else { maskedValue = _dateValue.getFullYear(); } break; case DateParts.Hours: if (datePartInfo.format.indexOf('h') !== -1) { maskedValue = DateTimeUtil.prependValue(DateTimeUtil.toTwelveHourFormat(_dateValue.getHours().toString()), partLength, '0'); } else { maskedValue = _dateValue.getHours(); } break; case DateParts.Minutes: maskedValue = _dateValue.getMinutes(); break; case DateParts.Seconds: maskedValue = _dateValue.getSeconds(); break; case DateParts.AmPm: maskedValue = _dateValue.getHours() >= 12 ? 'PM' : 'AM'; break; } if (datePartInfo.type !== DateParts.AmPm) { return DateTimeUtil.prependValue(maskedValue, partLength, '0'); } return maskedValue; } static spinYear(delta, newDate) { const maxDate = DateTimeUtil.daysInMonth(newDate.getFullYear() + delta, newDate.getMonth()); if (newDate.getDate() > maxDate) { newDate.setDate(maxDate); } newDate.setFullYear(newDate.getFullYear() + delta); return newDate; } static spinMonth(delta, newDate, spinLoop) { const maxDate = DateTimeUtil.daysInMonth(newDate.getFullYear(), newDate.getMonth() + delta); if (newDate.getDate() > maxDate) { newDate.setDate(maxDate); } const maxMonth = 11; const minMonth = 0; let month = newDate.getMonth() + delta; if (month > maxMonth) { month = spinLoop ? (month % maxMonth) - 1 : maxMonth; } else if (month < minMonth) { month = spinLoop ? maxMonth + (month % maxMonth) + 1 : minMonth; } newDate.setMonth(month); } static spinDate(delta, newDate, spinLoop) { const maxDate = DateTimeUtil.daysInMonth(newDate.getFullYear(), newDate.getMonth()); let date = newDate.getDate() + delta; if (date > maxDate) { date = spinLoop ? date % maxDate : maxDate; } else if (date < 1) { date = spinLoop ? maxDate + (date % maxDate) : 1; } newDate.setDate(date); } static spinHours(delta, newDate, spinLoop) { const maxHour = 23; const minHour = 0; let hours = newDate.getHours() + delta; if (hours > maxHour) { hours = spinLoop ? (hours % maxHour) - 1 : maxHour; } else if (hours < minHour) { hours = spinLoop ? maxHour + (hours % maxHour) + 1 : minHour; } newDate.setHours(hours); } static spinMinutes(delta, newDate, spinLoop) { const maxMinutes = 59; const minMinutes = 0; let minutes = newDate.getMinutes() + delta; if (minutes > maxMinutes) { minutes = spinLoop ? (minutes % maxMinutes) - 1 : maxMinutes; } else if (minutes < minMinutes) { minutes = spinLoop ? maxMinutes + (minutes % maxMinutes) + 1 : minMinutes; } newDate.setMinutes(minutes); } static spinSeconds(delta, newDate, spinLoop) { const maxSeconds = 59; const minSeconds = 0; let seconds = newDate.getSeconds() + delta; if (seconds > maxSeconds) { seconds = spinLoop ? (seconds % maxSeconds) - 1 : maxSeconds; } else if (seconds < minSeconds) { seconds = spinLoop ? maxSeconds + (seconds % maxSeconds) + 1 : minSeconds; } newDate.setSeconds(seconds); } static spinAmPm(newDate, currentDate, amPmFromMask) { let date = new Date(newDate); switch (amPmFromMask) { case 'AM': date = new Date(newDate.setHours(newDate.getHours() + 12)); break; case 'PM': date = new Date(newDate.setHours(newDate.getHours() - 12)); break; } if (date.getDate() !== currentDate.getDate()) { return currentDate; } return date; } static greaterThanMaxValue(value, maxValue, includeTime = true, includeDate = true) { if (includeTime && includeDate) { return value.getTime() > maxValue.getTime(); } const _value = new Date(value.getTime()); const _maxValue = new Date(maxValue.getTime()); if (!includeTime) { _value.setHours(0, 0, 0, 0); _maxValue.setHours(0, 0, 0, 0); } if (!includeDate) { _value.setFullYear(0, 0, 0); _maxValue.setFullYear(0, 0, 0); } return _value.getTime() > _maxValue.getTime(); } static lessThanMinValue(value, minValue, includeTime = true, includeDate = true) { if (includeTime && includeDate) { return value.getTime() < minValue.getTime(); } const _value = new Date(value.getTime()); const _minValue = new Date(minValue.getTime()); if (!includeTime) { _value.setHours(0, 0, 0, 0); _minValue.setHours(0, 0, 0, 0); } if (!includeDate) { _value.setFullYear(0, 0, 0); _minValue.setFullYear(0, 0, 0); } return _value.getTime() < _minValue.getTime(); } static validateMinMax(value, minValue, maxValue, includeTime = true, includeDate = true) { const errors = {}; const min = DateTimeUtil.isValidDate(minValue) ? minValue : DateTimeUtil.parseIsoDate(minValue); const max = DateTimeUtil.isValidDate(maxValue) ? maxValue : DateTimeUtil.parseIsoDate(maxValue); if (min && value && DateTimeUtil.lessThanMinValue(value, min, includeTime, includeDate)) { Object.assign(errors, { minValue: true }); } if (max && value && DateTimeUtil.greaterThanMaxValue(value, max, includeTime, includeDate)) { Object.assign(errors, { maxValue: true }); } return errors; } static setDisplayFormatOptions(value, format, locale, noLeadingZero = false) { const options = {}; const parts = DateTimeUtil.parseDateTimeFormat(format, locale, noLeadingZero); const datePartFormatOptionMap = new Map([ [DateParts.Date, 'day'], [DateParts.Month, 'month'], [DateParts.Year, 'year'], [DateParts.Hours, 'hour'], [DateParts.Minutes, 'minute'], [DateParts.Seconds, 'second'], [DateParts.AmPm, 'dayPeriod'], ]); const dateFormatMap = new Map([ ['d', 'numeric'], ['dd', '2-digit'], ['M', 'numeric'], ['MM', '2-digit'], ['MMM', 'short'], ['MMMM', 'long'], ['MMMMM', 'narrow'], ['y', 'numeric'], ['yy', '2-digit'], ['yyy', 'numeric'], ['yyyy', 'numeric'], ['h', 'numeric'], ['hh', '2-digit'], ['H', 'numeric'], ['HH', '2-digit'], ['m', 'numeric'], ['mm', '2-digit'], ['s', 'numeric'], ['ss', '2-digit'], ['ttt', 'short'], ['tttt', 'long'], ['ttttt', 'narrow'], ]); for (const part of parts) { if (part.type !== DateParts.Literal) { const option = datePartFormatOptionMap.get(part.type); const format = dateFormatMap.get(part.format) || dateFormatMap.get(part.format.substring(0, 2)); if (option && format) { options[option] = format; if (part.type === DateParts.Hours) { if (part.format.charAt(0) === 'h') { options.hourCycle = 'h12'; } else { options.hourCycle = 'h23'; } } } if (part.type === DateParts.AmPm && part.format.length <= 2) { options.hour = '2-digit'; options.hourCycle = 'h12'; } } } let formatter; try { formatter = new Intl.DateTimeFormat(locale, options); } catch { formatter = new Intl.DateTimeFormat(DateTimeUtil.DEFAULT_LOCALE, options); } const formattedParts = formatter.formatToParts(value); let result = ''; for (const part of parts) { if (part.type === DateParts.Literal) { result += part.format; continue; } const option = datePartFormatOptionMap.get(part.type); result += formattedParts.filter((p) => p.type === option)[0]?.value || ''; } return result; } static getMask(dateStruct) { const mask = []; for (const part of dateStruct) { switch (part.formatType) { case FormatDesc.Numeric: { if (part.type === DateParts.Day) { mask.push('d'); } else if (part.type === DateParts.Month) { mask.push('M'); } else { mask.push('yyyy'); } break; } case FormatDesc.TwoDigits: { if (part.type === DateParts.Day) { mask.push('dd'); } else if (part.type === DateParts.Month) { mask.push('MM'); } else { mask.push('yy'); } } } if (part.type === DateTimeUtil.SEPARATOR) { mask.push(part.value); } } return mask.join(''); } static addCurrentPart(currentPart, dateTimeParts, noLeadingZero = false) { DateTimeUtil.ensureLeadingZero(currentPart, noLeadingZero); currentPart.end = currentPart.start + currentPart.format.length; dateTimeParts.push(currentPart); } static ensureLeadingZero(part, noLeadingZero = false) { switch (part.type) { case DateParts.Date: case DateParts.Month: case DateParts.Hours: case DateParts.Minutes: case DateParts.Seconds: if (part.format.length === 1 && !noLeadingZero) { part.format = part.format.repeat(2); } break; } } static determineDatePart(char) { switch (char) { case 'd': case 'D': return DateParts.Date; case 'M': return DateParts.Month; case 'y': case 'Y': return DateParts.Year; case 'h': case 'H': return DateParts.Hours; case 'm': return DateParts.Minutes; case 's': case 'S': return DateParts.Seconds; case 't': case 'T': return DateParts.AmPm; default: return DateParts.Literal; } } static getDefaultLocaleMask(locale) { const dateStruct = []; let formatter; try { formatter = new Intl.DateTimeFormat(locale); } catch { return; } const formatToParts = formatter.formatToParts(new Date()); for (const part of formatToParts) { if (part.type === DateTimeUtil.SEPARATOR) { dateStruct.push({ type: DateTimeUtil.SEPARATOR, value: part.value, }); } else { dateStruct.push({ type: part.type, }); } } const formatterOptions = formatter.resolvedOptions(); for (const part of dateStruct) { switch (part.type) { case DateParts.Day: { part.formatType = formatterOptions.day; break; } case DateParts.Month: { part.formatType = formatterOptions.month; break; } case DateParts.Year: { part.formatType = formatterOptions.year; break; } } } DateTimeUtil.fillDatePartsPositions(dateStruct); return dateStruct; } static fillDatePartsPositions(dateArray) { let currentPos = 0; for (const part of dateArray) { if (part.type === DateParts.Day || part.type === DateParts.Month) { part.position = [currentPos, currentPos + 2]; currentPos += 2; } else if (part.type === DateParts.Year) { switch (part.formatType) { case FormatDesc.Numeric: { part.position = [currentPos, currentPos + 4]; currentPos += 4; break; } case FormatDesc.TwoDigits: { part.position = [currentPos, currentPos + 2]; currentPos += 2; break; } } } else if (part.type === DateTimeUtil.SEPARATOR) { part.position = [currentPos, currentPos + 1]; currentPos++; } } } static getCleanVal(inputData, datePart, prompt) { return DateTimeUtil.trimEmptyPlaceholders(inputData.substring(datePart.start, datePart.end), prompt); } static escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } static trimEmptyPlaceholders(value, prompt) { const result = value.replace(new RegExp(DateTimeUtil.escapeRegExp(prompt ?? '_'), 'g'), ''); return result; } static daysInMonth(fullYear, month) { return new Date(fullYear, month + 1, 0).getDate(); } static prependValue(value, partLength, prependChar) { return (prependChar + value.toString()).slice(-partLength); } static toTwelveHourFormat(value) { let hour = Number.parseInt(value.replace(new RegExp(DateTimeUtil.escapeRegExp(DateTimeUtil._parser.prompt), 'g'), '0'), 10); if (hour > 12) { hour -= 12; } else if (hour === 0) { hour = 12; } return hour; } } DateTimeUtil.DEFAULT_INPUT_FORMAT = 'MM/dd/yyyy'; DateTimeUtil.DEFAULT_TIME_INPUT_FORMAT = 'hh:mm tt'; DateTimeUtil.SEPARATOR = 'literal'; DateTimeUtil.DEFAULT_LOCALE = 'en'; DateTimeUtil._parser = new MaskParser(); //# sourceMappingURL=date-util.js.map