UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

127 lines (125 loc) 6.2 kB
/** * DevExtreme (cjs/__internal/scheduler/recurrence/generate_dates.js) * Version: 25.2.3 * Build date: Fri Dec 12 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.generateDates = void 0; var _date = require("../../core/utils/date"); var _rrule = require("rrule"); var _m_utils_time_zone = _interopRequireDefault(require("../m_utils_time_zone")); var _base = require("./base"); var _validate_rule = require("./validate_rule"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e } } const { addOffsets: addOffsets } = _date.dateUtilsTs; const MS_IN_HOUR = 36e5; const MS_IN_DAY = 864e5; const RRULE_BROKEN_TIMEZONES = ["Etc/GMT-13", "MIT", "Pacific/Apia", "Pacific/Enderbury", "Pacific/Tongatapu", "Etc/GMT-14", "Pacific/Kiritimati"]; const getRruleParams = options => { const { start: start, min: min, max: max, appointmentTimezoneOffset: appointmentTimezoneOffset } = options; const clientOffsets_startDate = _m_utils_time_zone.default.getClientTimezoneOffset(start), clientOffsets_minViewDate = _m_utils_time_zone.default.getClientTimezoneOffset(min), clientOffsets_maxViewDate = _m_utils_time_zone.default.getClientTimezoneOffset(max); const duration = options.end ? options.end.getTime() - options.start.getTime() : 0; const startIntervalDate = addOffsets(options.start, -clientOffsets_startDate, appointmentTimezoneOffset); const minViewTime = options.min.getTime() - clientOffsets_minViewDate + appointmentTimezoneOffset; const minViewDate = new Date(minViewTime - duration); const maxViewDate = addOffsets(options.max, -clientOffsets_maxViewDate, appointmentTimezoneOffset); const startDateDSTDifferenceMs = _m_utils_time_zone.default.getDiffBetweenClientTimezoneOffsets(options.start, startIntervalDate); const switchToSummerTime = startDateDSTDifferenceMs < 0; return { startIntervalDate: startIntervalDate, minViewTime: minViewTime, minViewDate: minViewDate, maxViewDate: maxViewDate, startIntervalDateDSTShift: switchToSummerTime ? 0 : startDateDSTDifferenceMs, appointmentDuration: duration } }; const getLocalMachineOffset = rruleDate => { const machineTimezoneOffset = _m_utils_time_zone.default.getClientTimezoneOffset(rruleDate); const machineTimezoneName = _m_utils_time_zone.default.getMachineTimezoneName(); const result = [machineTimezoneOffset]; const isTimezoneOffsetInBrokenRange = machineTimezoneOffset / 36e5 <= -13; const isTimezoneNameInBrokenNames = !machineTimezoneName || RRULE_BROKEN_TIMEZONES.some((timezone => machineTimezoneName.includes(timezone))); if (isTimezoneOffsetInBrokenRange && isTimezoneNameInBrokenNames) { result.push(-864e5) } return result }; const convertRruleResult = (rruleIntervalParams, options, rruleDate) => { const convertedBackDate = addOffsets(rruleDate, ...getLocalMachineOffset(rruleDate), -options.appointmentTimezoneOffset, rruleIntervalParams.startIntervalDateDSTShift); const convertedDateDSTShift = _m_utils_time_zone.default.getDiffBetweenClientTimezoneOffsets(convertedBackDate, rruleDate); const switchToSummerTime = convertedDateDSTShift < 0; const resultDate = addOffsets(convertedBackDate, convertedDateDSTShift); const resultDateDSTShift = _m_utils_time_zone.default.getDiffBetweenClientTimezoneOffsets(resultDate, convertedBackDate); if (resultDateDSTShift && switchToSummerTime) { return new Date(resultDate.getTime() + resultDateDSTShift) } return resultDate }; const createRRule = (options, startDateUtc, until) => { const ruleOptions = _rrule.RRule.parseString(String(options.rule)); const { firstDayOfWeek: firstDayOfWeek } = options; ruleOptions.dtstart = startDateUtc; if (!ruleOptions.wkst && firstDayOfWeek) { const weekDayNumbers = [6, 0, 1, 2, 3, 4, 5]; ruleOptions.wkst = weekDayNumbers[firstDayOfWeek] } if (until) { ruleOptions.until = addOffsets(until, -_m_utils_time_zone.default.getClientTimezoneOffset(until), options.appointmentTimezoneOffset) } const rRuleSet = new _rrule.RRuleSet; const rRule = new _rrule.RRule(ruleOptions); rRuleSet.rrule(rRule); if (options.exception) { const exceptionStrings = options.exception; const exceptionDates = exceptionStrings.split(",").map((rule => (0, _base.getDateByAsciiString)(rule))).filter(Boolean); exceptionDates.forEach((date => { const rruleTimezoneOffsets = "function" === typeof options.getExceptionDateTimezoneOffsets ? options.getExceptionDateTimezoneOffsets(date) : [-_m_utils_time_zone.default.getClientTimezoneOffset(date), options.appointmentTimezoneOffset]; const exceptionDateInPseudoUtc = addOffsets(date, ...rruleTimezoneOffsets); rRuleSet.exdate(exceptionDateInPseudoUtc) })) } return rRuleSet }; const generateDates = options => { if (!options.rule) { return [] } const rule = (0, _base.parseRecurrenceRule)(options.rule); const isValid = (0, _validate_rule.validateRRuleObject)(rule, options.rule); if (!isValid) { return [] } const rruleIntervalParams = getRruleParams(options); const { startIntervalDate: startIntervalDate, maxViewDate: maxViewDate, minViewDate: minViewDate, minViewTime: minViewTime, appointmentDuration: appointmentDuration } = rruleIntervalParams; const rRuleSet = createRRule(options, startIntervalDate, rule.until); return rRuleSet.between(minViewDate, maxViewDate, true).filter((date => date.getTime() + appointmentDuration >= minViewTime)).map((date => convertRruleResult(rruleIntervalParams, options, date))) }; exports.generateDates = generateDates;