UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

720 lines (694 loc) • 25.4 kB
/** * DevExtreme (cjs/__internal/core/utils/m_date.js) * Version: 24.2.6 * Build date: Mon Mar 17 2025 * * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.dateUtils = void 0; var _date_serialization = _interopRequireDefault(require("../../../core/utils/date_serialization")); var _inflector = require("../../../core/utils/inflector"); var _iterator = require("../../../core/utils/iterator"); var _math = require("../../../core/utils/math"); var _type = require("../../../core/utils/type"); var _toMilliseconds = require("../../utils/toMilliseconds"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } const DAYS_IN_WEEK = 7; const THURSDAY_WEEK_NUMBER = 4; const SUNDAY_WEEK_NUMBER = 7; const USUAL_WEEK_COUNT_IN_YEAR = 52; const dateUnitIntervals = ["millisecond", "second", "minute", "hour", "day", "week", "month", "quarter", "year"]; const getDatesInterval = function(startDate, endDate, intervalUnit) { const delta = endDate.getTime() - startDate.getTime(); const millisecondCount = (0, _toMilliseconds.toMilliseconds)(intervalUnit) || 1; return Math.floor(delta / millisecondCount) }; const getNextDateUnit = function(unit, withWeeks) { const interval = getDateUnitInterval(unit); switch (interval) { case "millisecond": return "second"; case "second": return "minute"; case "minute": return "hour"; case "hour": return "day"; case "day": return withWeeks ? "week" : "month"; case "week": return "month"; case "month": return "quarter"; case "quarter": case "year": return "year"; default: return 0 } }; const convertMillisecondsToDateUnits = function(value) { let i; let dateUnitCount; let dateUnitInterval; const dateUnitIntervals = ["millisecond", "second", "minute", "hour", "day", "month", "year"]; const result = {}; for (i = dateUnitIntervals.length - 1; i >= 0; i--) { dateUnitInterval = dateUnitIntervals[i]; dateUnitCount = Math.floor(value / (0, _toMilliseconds.toMilliseconds)(dateUnitInterval)); if (dateUnitCount > 0) { result[`${dateUnitInterval}s`] = dateUnitCount; value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount) } } return result }; const dateToMilliseconds = function(tickInterval) { let milliseconds = 0; if ((0, _type.isObject)(tickInterval)) { (0, _iterator.each)(tickInterval, (function(key, value) { milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value) })) } if ((0, _type.isString)(tickInterval)) { milliseconds = convertDateUnitToMilliseconds(tickInterval, 1) } return milliseconds }; function convertDateUnitToMilliseconds(dateUnit, count) { return (0, _toMilliseconds.toMilliseconds)(dateUnit) * count } function getDateUnitInterval(tickInterval) { let maxInterval = -1; let i; if ((0, _type.isString)(tickInterval)) { return tickInterval } if ((0, _type.isObject)(tickInterval)) { (0, _iterator.each)(tickInterval, (function(key, value) { for (i = 0; i < dateUnitIntervals.length; i++) { if (value && (key === `${dateUnitIntervals[i]}s` || key === dateUnitIntervals[i]) && maxInterval < i) { maxInterval = i } } })); return dateUnitIntervals[maxInterval] } return "" } const tickIntervalToFormatMap = { millisecond: "millisecond", second: "longtime", minute: "shorttime", hour: "shorttime", day: "day", week: "day", month: "month", quarter: "quarter", year: "year" }; function getDateFormatByTickInterval(tickInterval) { return tickIntervalToFormatMap[getDateUnitInterval(tickInterval)] || "" } const getQuarter = function(month) { return Math.floor(month / 3) }; const getFirstQuarterMonth = function(month) { return 3 * getQuarter(month) }; function correctDateWithUnitBeginning(date, dateInterval, withCorrection, firstDayOfWeek) { date = new Date(date.getTime()); const oldDate = new Date(date.getTime()); let firstQuarterMonth; let month; const dateUnitInterval = getDateUnitInterval(dateInterval); switch (dateUnitInterval) { case "second": date = new Date(1e3 * Math.floor(oldDate.getTime() / 1e3)); break; case "minute": date = new Date(6e4 * Math.floor(oldDate.getTime() / 6e4)); break; case "hour": date = new Date(36e5 * Math.floor(oldDate.getTime() / 36e5)); break; case "year": date.setMonth(0); case "month": date.setDate(1); case "day": date.setHours(0, 0, 0, 0); break; case "week": date = getFirstWeekDate(date, firstDayOfWeek || 0); date.setHours(0, 0, 0, 0); break; case "quarter": firstQuarterMonth = getFirstQuarterMonth(date.getMonth()); month = date.getMonth(); date.setDate(1); date.setHours(0, 0, 0, 0); if (month !== firstQuarterMonth) { date.setMonth(firstQuarterMonth) } } if (withCorrection && "hour" !== dateUnitInterval && "minute" !== dateUnitInterval && "second" !== dateUnitInterval) { fixTimezoneGap(oldDate, date) } return date } function trimTime(date) { return correctDateWithUnitBeginning(date, "day") } const setToDayEnd = function(date) { const result = trimTime(date); result.setDate(result.getDate() + 1); return new Date(result.getTime() - 1) }; const getDatesDifferences = function(date1, date2) { let counter = 0; const differences = { year: date1.getFullYear() !== date2.getFullYear(), month: date1.getMonth() !== date2.getMonth(), day: date1.getDate() !== date2.getDate(), hour: date1.getHours() !== date2.getHours(), minute: date1.getMinutes() !== date2.getMinutes(), second: date1.getSeconds() !== date2.getSeconds(), millisecond: date1.getMilliseconds() !== date2.getMilliseconds() }; (0, _iterator.each)(differences, (function(key, value) { if (value) { counter++ } })); if (0 === counter && 0 !== getTimezonesDifference(date1, date2)) { differences.hour = true; counter++ } differences.count = counter; return differences }; function addDateInterval(value, interval, dir) { const result = new Date(value.getTime()); const intervalObject = (0, _type.isString)(interval) ? getDateIntervalByString(interval.toLowerCase()) : (0, _type.isNumeric)(interval) ? convertMillisecondsToDateUnits(interval) : interval; if (intervalObject.years) { result.setFullYear(result.getFullYear() + intervalObject.years * dir) } if (intervalObject.quarters) { result.setMonth(result.getMonth() + 3 * intervalObject.quarters * dir) } if (intervalObject.months) { result.setMonth(result.getMonth() + intervalObject.months * dir) } if (intervalObject.weeks) { result.setDate(result.getDate() + 7 * intervalObject.weeks * dir) } if (intervalObject.days) { result.setDate(result.getDate() + intervalObject.days * dir) } if (intervalObject.hours) { result.setTime(result.getTime() + 36e5 * intervalObject.hours * dir) } if (intervalObject.minutes) { result.setTime(result.getTime() + 6e4 * intervalObject.minutes * dir) } if (intervalObject.seconds) { result.setTime(result.getTime() + 1e3 * intervalObject.seconds * dir) } if (intervalObject.milliseconds) { result.setTime(result.getTime() + intervalObject.milliseconds * dir) } return result } const addInterval = function(value, interval, isNegative) { const dir = isNegative ? -1 : 1; return (0, _type.isDate)(value) ? addDateInterval(value, interval, dir) : (0, _math.adjust)(value + interval * dir, interval) }; const getSequenceByInterval = function(min, max, interval) { const intervals = []; let cur; intervals.push((0, _type.isDate)(min) ? new Date(min.getTime()) : min); cur = min; while (cur < max) { cur = addInterval(cur, interval); intervals.push(cur) } return intervals }; const getViewFirstCellDate = function(viewType, date) { if ("month" === viewType) { return createDateWithFullYear(date.getFullYear(), date.getMonth(), 1) } if ("year" === viewType) { return createDateWithFullYear(date.getFullYear(), 0, date.getDate()) } if ("decade" === viewType) { return createDateWithFullYear(getFirstYearInDecade(date), date.getMonth(), date.getDate()) } if ("century" === viewType) { return createDateWithFullYear(getFirstDecadeInCentury(date), date.getMonth(), date.getDate()) } }; const getViewLastCellDate = function(viewType, date) { if ("month" === viewType) { return createDateWithFullYear(date.getFullYear(), date.getMonth(), getLastMonthDay(date)) } if ("year" === viewType) { return createDateWithFullYear(date.getFullYear(), 11, date.getDate()) } if ("decade" === viewType) { return createDateWithFullYear(getFirstYearInDecade(date) + 9, date.getMonth(), date.getDate()) } if ("century" === viewType) { return createDateWithFullYear(getFirstDecadeInCentury(date) + 90, date.getMonth(), date.getDate()) } }; const getViewMinBoundaryDate = function(viewType, date) { const resultDate = createDateWithFullYear(date.getFullYear(), date.getMonth(), 1); if ("month" === viewType) { return resultDate } resultDate.setMonth(0); if ("year" === viewType) { return resultDate } if ("decade" === viewType) { resultDate.setFullYear(getFirstYearInDecade(date)) } if ("century" === viewType) { resultDate.setFullYear(getFirstDecadeInCentury(date)) } return resultDate }; const getViewMaxBoundaryDate = function(viewType, date) { const resultDate = new Date(date); resultDate.setDate(getLastMonthDay(date)); if ("month" === viewType) { return resultDate } resultDate.setMonth(11); resultDate.setDate(getLastMonthDay(resultDate)); if ("year" === viewType) { return resultDate } if ("decade" === viewType) { resultDate.setFullYear(getFirstYearInDecade(date) + 9) } if ("century" === viewType) { resultDate.setFullYear(getFirstDecadeInCentury(date) + 99) } return resultDate }; function getLastMonthDay(date) { const resultDate = createDateWithFullYear(date.getFullYear(), date.getMonth() + 1, 0); return resultDate.getDate() } const getViewUp = function(typeView) { switch (typeView) { case "month": return "year"; case "year": return "decade"; case "decade": return "century" } }; const getViewDown = function(typeView) { switch (typeView) { case "century": return "decade"; case "decade": return "year"; case "year": return "month" } }; const getDifferenceInMonth = function(typeView) { let difference = 1; if ("year" === typeView) { difference = 12 } if ("decade" === typeView) { difference = 120 } if ("century" === typeView) { difference = 1200 } return difference }; const getDifferenceInMonthForCells = function(typeView) { let difference = 1; if ("decade" === typeView) { difference = 12 } if ("century" === typeView) { difference = 120 } return difference }; function getDateIntervalByString(intervalString) { const result = {}; switch (intervalString) { case "year": result.years = 1; break; case "month": result.months = 1; break; case "quarter": result.months = 3; break; case "week": result.weeks = 1; break; case "day": result.days = 1; break; case "hour": result.hours = 1; break; case "minute": result.minutes = 1; break; case "second": result.seconds = 1; break; case "millisecond": result.milliseconds = 1 } return result } function sameDate(date1, date2) { return sameMonthAndYear(date1, date2) && date1.getDate() === date2.getDate() } function sameMonthAndYear(date1, date2) { return sameYear(date1, date2) && date1.getMonth() === date2.getMonth() } function sameYear(date1, date2) { return date1 && date2 && date1.getFullYear() === date2.getFullYear() } function sameHoursAndMinutes(date1, date2) { return date1 && date2 && date1.getHours() === date2.getHours() && date1.getMinutes() === date2.getMinutes() } const sameDecade = function(date1, date2) { if (!(0, _type.isDefined)(date1) || !(0, _type.isDefined)(date2)) { return } const startDecadeDate1 = date1.getFullYear() - date1.getFullYear() % 10; const startDecadeDate2 = date2.getFullYear() - date2.getFullYear() % 10; return date1 && date2 && startDecadeDate1 === startDecadeDate2 }; const sameCentury = function(date1, date2) { if (!(0, _type.isDefined)(date1) || !(0, _type.isDefined)(date2)) { return } const startCenturyDate1 = date1.getFullYear() - date1.getFullYear() % 100; const startCenturyDate2 = date2.getFullYear() - date2.getFullYear() % 100; return date1 && date2 && startCenturyDate1 === startCenturyDate2 }; function getFirstDecadeInCentury(date) { return date && date.getFullYear() - date.getFullYear() % 100 } function getFirstYearInDecade(date) { return date && date.getFullYear() - date.getFullYear() % 10 } const getShortDateFormat = function() { return "yyyy/MM/dd" }; const getFirstMonthDate = function(date) { let offset = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0; if (!(0, _type.isDefined)(date)) { return } const currentDate = new Date(date.getTime()); const month = currentDate.getMonth() + offset; currentDate.setMonth(month); return createDateWithFullYear(currentDate.getFullYear(), month, 1) }; const getLastMonthDate = function(date) { let offset = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0; if (!(0, _type.isDefined)(date)) { return } const currentDate = new Date(date.getTime()); const month = currentDate.getMonth() + offset; currentDate.setMonth(month); return createDateWithFullYear(currentDate.getFullYear(), month + 1, 0) }; function getFirstWeekDate(date, firstDayOfWeek) { const delta = (date.getDay() - firstDayOfWeek + 7) % 7; const result = new Date(date); result.setDate(date.getDate() - delta); return result } function getUTCTime(date) { return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) } function getDayNumber(date) { const ms = getUTCTime(date) - getUTCTime(getFirstDateInYear(date.getFullYear())); return 1 + Math.floor(ms / (0, _toMilliseconds.toMilliseconds)("day")) } function getFirstDateInYear(year) { return new Date(year, 0, 1) } function getLastDateInYear(year) { return new Date(year, 11, 31) } function getDayWeekNumber(date, firstDayOfWeek) { let day = date.getDay() - firstDayOfWeek + 1; if (day <= 0) { day += 7 } return day } function getWeekNumber(date, firstDayOfWeek, rule) { const firstWeekDayInYear = getDayWeekNumber(getFirstDateInYear(date.getFullYear()), firstDayOfWeek); const lastWeekDayInYear = getDayWeekNumber(getLastDateInYear(date.getFullYear()), firstDayOfWeek); const daysInFirstWeek = 7 - firstWeekDayInYear + 1; let weekNumber = Math.ceil((getDayNumber(date) - daysInFirstWeek) / 7); switch (rule) { case "fullWeek": if (7 === daysInFirstWeek) { weekNumber++ } if (0 === weekNumber) { const lastDateInPreviousYear = getLastDateInYear(date.getFullYear() - 1); return getWeekNumber(lastDateInPreviousYear, firstDayOfWeek, rule) } return weekNumber; case "firstDay": { if (daysInFirstWeek > 0) { weekNumber++ } const isSunday = 7 === firstWeekDayInYear || 7 === lastWeekDayInYear; if (weekNumber > 52 && !isSunday || 54 === weekNumber) { weekNumber = 1 } return weekNumber } case "firstFourDays": { if (daysInFirstWeek > 3) { weekNumber++ } const isThursday = 4 === firstWeekDayInYear || 4 === lastWeekDayInYear; if (weekNumber > 52 && !isThursday) { weekNumber = 1 } if (0 === weekNumber) { const lastDateInPreviousYear = getLastDateInYear(date.getFullYear() - 1); return getWeekNumber(lastDateInPreviousYear, firstDayOfWeek, rule) } return weekNumber } } } const normalizeDateByWeek = function(date, currentDate) { const differenceInDays = dateUtils.getDatesInterval(date, currentDate, "day"); let resultDate = new Date(date); if (differenceInDays >= 6) { resultDate = new Date(resultDate.setDate(resultDate.getDate() + 7)) } return resultDate }; const dateInRange = function(date, min, max, format) { if ("date" === format) { min = min && dateUtils.correctDateWithUnitBeginning(min, "day"); max = max && dateUtils.correctDateWithUnitBeginning(max, "day"); date = date && dateUtils.correctDateWithUnitBeginning(date, "day") } return normalizeDate(date, min, max) === date }; const intervalsOverlap = function(options) { const { firstMin: firstMin, firstMax: firstMax, secondMin: secondMin, secondMax: secondMax } = options; return firstMin <= secondMin && secondMin <= firstMax || firstMin > secondMin && firstMin < secondMax || firstMin < secondMax && firstMax > secondMax }; const dateTimeFromDecimal = function(number) { const hours = Math.floor(number); const minutes = number % 1 * 60; return { hours: hours, minutes: minutes } }; const roundDateByStartDayHour = function(date, startDayHour) { const startTime = this.dateTimeFromDecimal(startDayHour); const result = new Date(date); if (date.getHours() === startTime.hours && date.getMinutes() < startTime.minutes || date.getHours() < startTime.hours) { result.setHours(startTime.hours, startTime.minutes, 0, 0) } return result }; function normalizeDate(date, min, max) { let normalizedDate = date; if (!(0, _type.isDefined)(date)) { return date } if ((0, _type.isDefined)(min) && date < min) { normalizedDate = min } if ((0, _type.isDefined)(max) && date > max) { normalizedDate = max } return normalizedDate } function fixTimezoneGap(oldDate, newDate) { if (!(0, _type.isDefined)(oldDate)) { return } const diff = newDate.getHours() - oldDate.getHours(); if (0 === diff) { return } const sign = 1 === diff || -23 === diff ? -1 : 1; const trial = new Date(newDate.getTime() + 36e5 * sign); if (sign > 0 || trial.getDate() === newDate.getDate()) { newDate.setTime(trial.getTime()) } } const roundToHour = function(date) { const result = new Date(date.getTime()); result.setHours(result.getHours() + 1); result.setMinutes(0); return result }; function getTimezonesDifference(min, max) { return 60 * (max.getTimezoneOffset() - min.getTimezoneOffset()) * 1e3 } const makeDate = function(date) { return new Date(date) }; const getDatesOfInterval = function(startDate, endDate, step) { const result = []; let currentDate = new Date(startDate.getTime()); while (currentDate < endDate) { result.push(new Date(currentDate.getTime())); currentDate = this.addInterval(currentDate, step) } return result }; const createDateWithFullYear = function(year) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key] } const result = new Date(year, ...args); result.setFullYear(year); return result }; const getMachineTimezoneName = () => { const hasIntl = "undefined" !== typeof Intl; return hasIntl ? Intl.DateTimeFormat().resolvedOptions().timeZone : null }; const getRangesByDates = dates => { const datesInMilliseconds = dates.map((value => correctDateWithUnitBeginning(value, "day").getTime())); const sortedDates = datesInMilliseconds.sort(((a, b) => a - b)); const msInDay = (0, _toMilliseconds.toMilliseconds)("day"); const ranges = []; let startDate = sortedDates[0]; for (let i = 1; i <= sortedDates.length; ++i) { const nextDate = sortedDates[i]; const currentDate = sortedDates[i - 1]; const isNewRange = nextDate - currentDate > msInDay; if (isNewRange || i === sortedDates.length) { const range = startDate === sortedDates[i - 1] ? [startDate] : [startDate, sortedDates[i - 1]]; const serializedRange = range.map((value => _date_serialization.default.deserializeDate(value))); ranges.push(serializedRange); startDate = nextDate } } return ranges }; const sameView = function(view, date1, date2) { return dateUtils[(0, _inflector.camelize)(`same ${view}`)](date1, date2) }; const dateUtils = exports.dateUtils = { dateUnitIntervals: dateUnitIntervals, convertMillisecondsToDateUnits: convertMillisecondsToDateUnits, dateToMilliseconds: dateToMilliseconds, getNextDateUnit: getNextDateUnit, convertDateUnitToMilliseconds: convertDateUnitToMilliseconds, getDateUnitInterval: getDateUnitInterval, getDateFormatByTickInterval: getDateFormatByTickInterval, getDatesDifferences: getDatesDifferences, correctDateWithUnitBeginning: correctDateWithUnitBeginning, trimTime: trimTime, setToDayEnd: setToDayEnd, roundDateByStartDayHour: roundDateByStartDayHour, dateTimeFromDecimal: dateTimeFromDecimal, addDateInterval: addDateInterval, addInterval: addInterval, getSequenceByInterval: getSequenceByInterval, getDateIntervalByString: getDateIntervalByString, sameHoursAndMinutes: sameHoursAndMinutes, sameDate: sameDate, sameMonthAndYear: sameMonthAndYear, sameMonth: sameMonthAndYear, sameYear: sameYear, sameDecade: sameDecade, sameCentury: sameCentury, sameView: sameView, getDifferenceInMonth: getDifferenceInMonth, getDifferenceInMonthForCells: getDifferenceInMonthForCells, getFirstYearInDecade: getFirstYearInDecade, getFirstDecadeInCentury: getFirstDecadeInCentury, getShortDateFormat: getShortDateFormat, getViewFirstCellDate: getViewFirstCellDate, getViewLastCellDate: getViewLastCellDate, getViewDown: getViewDown, getViewUp: getViewUp, getLastMonthDay: getLastMonthDay, getLastMonthDate: getLastMonthDate, getFirstMonthDate: getFirstMonthDate, getFirstWeekDate: getFirstWeekDate, getWeekNumber: getWeekNumber, normalizeDateByWeek: normalizeDateByWeek, getQuarter: getQuarter, getFirstQuarterMonth: getFirstQuarterMonth, dateInRange: dateInRange, intervalsOverlap: intervalsOverlap, roundToHour: roundToHour, normalizeDate: normalizeDate, getViewMinBoundaryDate: getViewMinBoundaryDate, getViewMaxBoundaryDate: getViewMaxBoundaryDate, fixTimezoneGap: fixTimezoneGap, getTimezonesDifference: getTimezonesDifference, makeDate: makeDate, getDatesInterval: getDatesInterval, getDatesOfInterval: getDatesOfInterval, createDateWithFullYear: createDateWithFullYear, getMachineTimezoneName: getMachineTimezoneName, getRangesByDates: getRangesByDates };