'use strict'; var CalDate = require('caldate'); var utils = require('./internal/utils.cjs'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var CalDate__default = /*#__PURE__*/_interopDefaultLegacy(CalDate); /** * handle rule per event */ class Rule { /** * @param {CalEvent} [calEvent] * @param {array} [holidays] */ constructor (calEvent) { this.calEvent = calEvent; } /** * @param {CalEvent} calEvent */ setEvent (calEvent) { this.calEvent = calEvent; return this } /** * @return {CalEvent} */ getEvent () { return this.calEvent } /** * @param {string} modifier */ setModifier (modifier) { this.modifier = modifier; } /** * resolves rule to function * @param {object} rule */ resolve (rule) { if (rule.rule && typeof this[rule.rule] === 'function' ) { this[rule.rule](rule); } else if (rule.modifier) { this.modifier = rule.modifier; } return this } /** * @param {CalEvent} [calEvent] * @param {object} rule * { * rule: "dateDir", * count: 1, * weekday: "tuesday", * direction: "after", * omit: ['sunday'] * } */ dateDir (rule) { const omitWeekdays = ([].concat(rule.omit)).map(weekday => utils.DAYS[weekday]).filter(v => !utils.isNil(v)); const isOmitDay = (offset, weekday) => { let wd = offset + weekday; while (wd < 0) { wd += 70; } return omitWeekdays.includes(wd % 7) }; this.calEvent.dates.forEach((date) => { let offset; let count = rule.count - 1; const weekday = date.getDay(); const ruleWeekday = utils.DAYS[rule.weekday]; const isDirBefore = ['before', 'previous'].includes(rule.direction); // correct count if weekday is same for next direction if (rule.direction === 'next' && weekday === ruleWeekday) { count += 1; } if (rule.weekday === 'day') { let i = 0; if (isDirBefore) { offset = (count + 1) * -1; while (i++ < 7 && isOmitDay(offset, weekday)) { offset -= 1; } } else { offset = count + 1; while (i++ < 7 && isOmitDay(offset, weekday)) { offset += 1; } } } else { if (isDirBefore) { if (weekday === ruleWeekday) { count++; } offset = ((7 + weekday - ruleWeekday) % 7 + count * 7) * -1; } else { offset = ((7 - weekday + ruleWeekday) % 7 + count * 7); } } if (offset) { date.setOffset(offset); } }); } /** * @param {object} rule * { * rule: "dateIfThen", * if: ["sunday"], * direction: "next", * then: "sunday" * } */ dateIfThen (rule) { const dates = []; this.calEvent.dates = this.calEvent.dates.map((date) => { if (date._lock) { return date } const weekday = date.getDay(); if (~(rule.if).indexOf(utils.DAYS[weekday])) { if (this.modifier === 'and') { dates.push(new CalDate__default["default"](date)); date.substitute = true; } date._filter = false; let offset = 0; const then = utils.DAYS[rule.then]; if (rule.then && then !== 'undefined') { if (rule.direction === 'previous') { offset = -1 * ((7 + weekday - then) % 7); if (!offset) { offset = -7; } } else { offset = ((7 - weekday + then) % 7); if (!offset) { offset = 7; } } date.setOffset(offset); date._lock = true; if (this.modifier === 'substitutes') date.substitute = true; } (rule.rules || []).forEach((rule) => { switch (rule.rule) { case 'time': date.setTime(rule.hour, rule.minute); break case 'duration': date.duration = rule.duration; break } }); } else if (this.modifier === 'substitutes') { date._filter = true; } return date }); this.calEvent.dates = dates.concat(this.calEvent.dates); } /** * @param {object} rule * { * rule: "weekday", * if: ["sunday", "saturday"], * not: false, * } */ weekday (rule) { this.calEvent.dates = this.calEvent.dates.map((date) => { const weekday = date.getDay(); let match = (rule.if).indexOf(utils.DAYS[weekday]) !== -1; if (rule.not) match = !match; if (match) return date }).filter(date => date); } time (rule) { this.calEvent.dates.forEach((date) => { date.setTime(rule.hour, rule.minute); }); } duration (rule) { this.calEvent.dates.forEach((date) => { date.duration = rule.duration; }); } bridge () { return true // needs postprocessing } ruleIfHoliday () { return true // needs postprocessing } activeFrom (rule) { this.calEvent.setActive({ from: new CalDate__default["default"](rule).toDate() }); } activeTo (rule) { this.calEvent.setActive({ to: new CalDate__default["default"](rule).toDate() }); } /** * @param {object} rule * { * rule: "year", * cardinality: "leap", * every: undefined, * since: undefined * } */ year (rule) { this.calEvent.dates = this.calEvent.dates.map((date) => { if (rule.cardinality) { if (rule.cardinality === 'leap' && this._isLeapYear(date.year)) { return date } else if (rule.cardinality === 'non-leap' && !this._isLeapYear(date.year)) { return date } else if (rule.cardinality === 'even' && (date.year + 1) % 2) { return date } else if (rule.cardinality === 'odd' && date.year % 2) { return date } } else if (rule.every !== undefined && rule.since !== undefined) { const tmp = (date.year - rule.since) % rule.every; if (tmp === 0) { return date } } }).filter(date => date); } /** * @private * @return {Boolean} if true year is a leap year */ _isLeapYear (year) { if ((year % 400 === 0) || (year % 4 === 0 && year % 100 !== 0)) { return true } return false } } module.exports = Rule;