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
JavaScript
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