UNPKG

moment-recur-ts

Version:

A momentjs plugin for matching and generating recurring dates.

1,263 lines (1,241 loc) 46.2 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("moment")); else if(typeof define === 'function' && define.amd) define("moment-recur-ts", ["moment"], factory); else if(typeof exports === 'object') exports["moment-recur-ts"] = factory(require("moment")); else root["moment-recur-ts"] = factory(root["moment"]); })(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 1); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_0__; /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var moment = __webpack_require__(0); var recur_1 = __webpack_require__(2); moment.fn.monthWeek = function (week) { if (week === undefined) { // First day of the first week of the month var week0 = this.clone().startOf('month').startOf('week'); // First day of week var day0 = this.clone().startOf('week'); return day0.diff(week0, 'weeks'); } else { var weekDiff = week - this.monthWeek(); return this.clone().add(weekDiff, 'weeks'); } }; moment.fn.monthWeekByDay = function (week) { if (week === undefined) { return Math.floor((this.date() - 1) / 7); } else { var weekDiff = week - this.monthWeekByDay(); return this.clone().add(weekDiff, 'weeks'); } }; // Plugin for removing all time information from a given date moment.fn.dateOnly = function () { // return this.startOf('day') return this.isValid() ? moment.utc(this.format('YYYY-MM-DD')) : this; }; moment.recur = function (start, end) { // If we have an object, use it as a set of options if (typeof start === 'object' && !moment.isMoment(start)) { var options = start; return new recur_1.Recur(options); } // else, use the values passed return new recur_1.Recur({ start: start, end: end }); }; moment.fn.recur = function (start, end) { // If we have an object, use it as a set of options if (start === Object(start) && !moment.isMoment(start)) { var options = start; // if we have no start date, use the moment if (options.start === undefined) { options.start = this; } return new recur_1.Recur(options); } // if there is no end value, use the start value as the end if (!end) { end = start; start = undefined; } // use the moment for the start value if (!start) { start = this; } return new recur_1.Recur({ start: start, end: end }); }; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [0, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; if (m) return m.call(o); return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; }; Object.defineProperty(exports, "__esModule", { value: true }); var moment = __webpack_require__(0); var rule_1 = __webpack_require__(3); /** * @internal * @hidden */ var ISO_DATE_FMT = 'YYYY-MM-DD'; /** * The main Recur object to provide an interface for settings, rules, and matching * * Creating Rules * -------------- * moment-recur-ts uses rules to define when a date should recur. You can then generate future * or past recurrences based on these rules, or see if a specific date matches the rules. * Rules can also be overridden or removed. * * ### Length Intervals * moment-recur-ts supports intervals for days, weeks, months, and years. Measurements may be singular or * plural (ex: `day()` vs `days()`). Length Intervals **must** have a start date defined. * * Possible Length Intervals Include: * * day / days * * week / weeks * * month / months * * year / years * * ### Calendar Intervals * Calendar Intervals do not depend on a start date. They define a unit of another unit. For instance, * a day of a month, or a month of a year. Measurements may be singular or plural * (ex: `dayOfMonth()` vs `daysOfMonth()`). * * Possible Calendar Intervals Include: * * dayOfWeek / daysOfWeek * * dayOfMonth / daysOfMonth * * weekOfMonth / weeksOfMonth * * weekOfYear / weeksOfYear * * monthOfYear / monthsOfYear */ var Recur = /** @class */ (function () { /** * ### Recur Object Constrcutor * * From an instance of moment: * ```js * let recurrence; * * // Create a recurrence using today as the start date. * recurrence = moment().recur(); * * // Create a recurrence while passing the start and end dates to the recur function. * // Note: passing an end date requires you to also pass a start date. * recurrence = moment().recur( start, end ); * * // You may pass a start date to the moment, or use an existing moment, to set the start date. * // In this case, passing a date to the recur function sets and end date. * recurrence = moment(start).recur( end ); * * // Finally, you can create a recurrence and pass in an entire set of options. * recurrence = moment().recur({ * start: "01/01/2014", * end: "01/01/2015" * }); * ``` * From static moment: * ```js * // Create recurrence without a start date. Note: this will not work with intervals. * recurrence = moment.recur(); * * // Create a recurrence, passing just the start, or the start and end dates. * recurrence = moment.recur( start, end ); * * // Create a recurrence, passing set of options. * recurrence = moment.recur({ * start: "01/01/2014", * end: "01/01/2015" * }); * ``` */ function Recur(options) { var _this = this; /** * @internal * @hidden */ this.reversed = false; /** * @internal * @hidden */ this.maximumYears = 1000; if (options.start) { this.start = moment(options.start).dateOnly(); } if (options.end) { this.end = moment(options.end).dateOnly(); } // Our list of rules, all of which must match this.rules = (options.rules || []).map(function (rule) { return rule_1.Rule.factory(rule.units, rule.measure, _this.start); }); // Our list of exceptions. Match always fails on these dates. var exceptions = options.exceptions || []; this.exceptions = exceptions.map(function (ex) { return moment(ex).dateOnly(); }); // Temporary units integer, array, or object. Does not get imported/exported. this.units = null; // Temporary measure type. Does not get imported/exported. this.measure = null; // Temporary from date for next/previous. Does not get imported/exported. this.from = null; this.addMeasureFunctions(); return this; } Recur.prototype.startDate = function (date) { if (date === null) { this.start = null; return this; } if (date) { this.start = moment(date).dateOnly(); return this; } if (!this.start) { throw new Error('No start date defined for recurrence.'); } return this.start; }; Recur.prototype.endDate = function (date) { if (date === null) { this.end = null; return this; } if (date) { this.end = moment(date).dateOnly(); return this; } if (!this.end) { throw new Error('No end date defined for recurrence.'); } return this.end; }; Recur.prototype.fromDate = function (date) { if (date === null) { this.from = null; return this; } if (date) { this.from = moment(date).dateOnly(); return this; } if (!this.from) { throw new Error('No from date defined for recurrence.'); } return this.from; }; Recur.prototype.maxYears = function (years) { if (years) { this.maximumYears = years; return this; } else { return this.maximumYears; } }; /** * Use `save()` to export all options, rules, and exceptions as an object. * This can be used to store recurrences in a database. * > Note: This does not export the "From Date" which is considered a temporary option. * ```js * recurrence.save(); * ``` */ Recur.prototype.save = function () { var data = {}; if (this.start && moment(this.start).isValid()) { data.start = this.start.format(ISO_DATE_FMT); } if (this.end && moment(this.end).isValid()) { data.end = this.end.format(ISO_DATE_FMT); } data.exceptions = this.exceptions.map(function (date) { return date.format(ISO_DATE_FMT); }); data.rules = this.rules; return data; }; /** * Use `repeats()` to check if a recurrence has rules set. * ```js * recurrence.repeats(); // true/false * ``` */ Recur.prototype.repeats = function () { return this.rules.length > 0; }; /** * The `every()` function allows you to set the units and, optionally, the measurment type * of the recurring date. It returns the recur object to allow chaining. * * ```js * let myDate, recurrence; * * // Create a date to start from * myDate = moment("01/01/2014"); * * // You can pass the units to recur on, and the measurement type. * recurrence = myDate.recur().every(1, "days"); * * // You can also chain the measurement type instead of passing it to every. * recurrence = myDate.recur().every(1).day(); * * // It is also possible to pass an array of units. * recurrence = myDate.recur().every([3, 5]).days(); * * // When using the dayOfWeek measurement, you can pass days names. * recurrence = myDate.recur().every(["Monday", "wed"]).daysOfWeek(); * * // Month names also work when using monthOfYear. * recurrence = myDate.recur().every(["Jan", "february"], "monthsOfYear"); * ``` * * `every()` will override the last "every" if a measurement was not provided. * The following line will create a recurrence for every 5 days. * ```js * recurrence = myDate.recur().every(1).every(5).days(); * ``` * If you need to specify multiple units, pass an array to `every()`. * * You may also pass the units directly to the interval functions (listed below) * instead of using `every()`. * ```js * let recurrence = moment.recur().monthOfYear("January"); * ``` */ Recur.prototype.every = function (units, measure) { if (units != null) { this.units = units; } if (measure != null) { this.measure = measure; } // Don't create the rule until measure is defined if (!this.measure) { return this; } var rule = rule_1.Rule.factory(this.units, this.measure, this.start); if (rule.measure === 'weeksOfMonthByDay' && !this.hasRule('daysOfWeek')) { throw new Error('weeksOfMonthByDay must be combined with daysOfWeek'); } // Remove the temporary rule data this.units = null; this.measure = null; // Remove existing rule based on measure this.rules = this.rules.filter(function (oldRule) { return oldRule.measure !== rule.measure; }); this.rules.push(rule); return this; }; /** * To prevent a date from matching that would normally match, use the `except()` function. * ```js * let recurrence = moment("01/01/2014").recur().every(1).day().except("01/02/2014"); * recurrence.matches("01/02/2014"); // false * ``` */ Recur.prototype.except = function (date) { date = moment(date).dateOnly(); this.exceptions.push(date); return this; }; /** * Forgets rules (by passing measure) and exceptions (by passing date) * ```js * // Exceptions can be removed by passing a date to the forget() function. * recurrence.forget("01/03/2014"); * ``` * ```js * // Rules can be removed by passing the measurement to the forget() function. * recurrence.forget("days"); * ``` */ Recur.prototype.forget = function (dateOrRule, format) { if (!dateOrRule) { throw new Error('Invalid input for recurrence forget: ' + dateOrRule); } try { var normMeasure_1 = rule_1.Rule.normalizeMeasure(dateOrRule); this.rules = this.rules.filter(function (rule) { return rule.measure !== normMeasure_1; }); return this; } catch (err) { var date_1 = moment(dateOrRule, format); // If valid date, try to remove it from exceptions if (date_1.isValid()) { date_1 = date_1.dateOnly(); // change to date only for perfect comparison this.exceptions = this.exceptions.filter(function (exception) { return !date_1.isSame(exception); }); return this; } else { throw new Error('Invalid input for recurrence forget: ' + dateOrRule); } } }; /** * Checks if a rule has been set on the chain */ Recur.prototype.hasRule = function (measure) { return this.rules.findIndex(function (rule) { return rule.measure === rule_1.Rule.normalizeMeasure(measure); }) !== -1; }; /** * The `matches()` function will test a date to check if all of the recurrence rules match. * It returns `true` if the date matches, `false` otherwise. * ```js * let interval = moment("01/01/2014").recur().every(2).days(); * interval.matches("01/02/2014"); // false * interval.matches("01/03/2014"); // true * ``` * * You may also see if a date matches before the start date or after the end date by * passing `true` as the second argument to `matches()`. * ```js * let interval = moment("01/01/2014").recur().every(2).days(); * interval.matches("12/30/2013"); // false * interval.matches("12/30/2013", true); // true * ``` */ Recur.prototype.matches = function (dateToMatch, ignoreStartEnd) { var date = moment(dateToMatch).dateOnly(); if (!date.isValid()) { throw Error('Invalid date supplied to match method: ' + dateToMatch); } if (!ignoreStartEnd && !this.inRange(date)) { return false; } if (this.isException(date)) { return false; } if (!this.matchAllRules(date)) { return false; } // if we passed everything above, then this date matches return true; }; /** * Iterate over moments matched by rules * > Note if there is no end date, results are unbounded (you must manually terminate the iterator). * * > Also note, this exapmle intentionally ignores some complicated leap year math. * * ```js * let recurrence = moment('2012-01').recur('2032-01').every(4).years() * let leapYears = [...recurrence].map(m => m.year()) * // leapYears = [ 2012, 2016, 2020, 2024, 2028, 2032 ] * ``` * Or, this is a bit faster... * ```js * let recurrence = moment('2012-01').recur('2032-01').every(4).years() * let leapYears = [] * for (let date of recurrence) { * leapYears.push(date.year()) * } * // leapYears = [ 2012, 2016, 2020, 2024, 2028, 2032 ] * ``` */ Recur.prototype[Symbol.iterator] = function () { var startFrom, currentDate; return __generator(this, function (_a) { switch (_a.label) { case 0: startFrom = this.from || this.start; if (!startFrom || !startFrom.isValid()) { throw Error('Cannot get occurrences without start or from date.'); } if (this.end && (startFrom > this.end)) { throw Error('Start date cannot be later than end date.'); } currentDate = startFrom.clone(); if (!this.matchAllRules(currentDate)) return [3 /*break*/, 2]; return [4 /*yield*/, currentDate.clone()]; case 1: _a.sent(); _a.label = 2; case 2: if (false) return [3 /*break*/, 5]; try { currentDate = this.reversed ? this.findPreviousMatch(currentDate) : this.findNextMatch(currentDate); } catch (err) { /* istanbul ignore else */ if (err instanceof RangeError) return [2 /*return*/, undefined]; else throw err; } if (this.end && currentDate.isAfter(this.end)) return [3 /*break*/, 5]; if (!!this.isException(currentDate)) return [3 /*break*/, 4]; return [4 /*yield*/, currentDate.clone()]; case 3: _a.sent(); _a.label = 4; case 4: return [3 /*break*/, 2]; case 5: return [2 /*return*/]; } }); }; /** * Reverse iterator direction * > Note since there is no end date, results are unbounded (you must manually terminate the iterator). * * ```js * let mondays = [] * for (let monday of moment().recur().every('Monday').dayOfWeek().reverse()) { * lastThreeMondays.push(monday) * if (mondays.length > 10) break * } * ``` */ Recur.prototype.reverse = function () { this.reversed = !this.reversed; return this; }; Recur.prototype.all = function (format) { if (!this.end || !this.end.isValid()) { throw Error('Cannot get all occurrences without an end date.'); } this.reversed = false; var dates = []; try { for (var _a = __values(this), _b = _a.next(); !_b.done; _b = _a.next()) { var date = _b.value; dates.push(format ? date.format(format) : date); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_b && !_b.done && (_c = _a.return)) _c.call(_a); } finally { if (e_1) throw e_1.error; } } return dates; var e_1, _c; }; Recur.prototype.next = function (num, format) { if (!num) return []; var dates = []; var count = 0; this.reversed = false; try { for (var _a = __values(this), _b = _a.next(); !_b.done; _b = _a.next()) { var date = _b.value; if (!(this.start && date.isSame(this.start))) { dates.push(format ? date.format(format) : date); count++; } if (count >= num) break; } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_b && !_b.done && (_c = _a.return)) _c.call(_a); } finally { if (e_2) throw e_2.error; } } return dates; var e_2, _c; }; Recur.prototype.previous = function (num, format) { if (!num) return []; var dates = []; var count = 0; this.reversed = true; try { for (var _a = __values(this), _b = _a.next(); !_b.done; _b = _a.next()) { var date = _b.value; if (!(this.start && date.isSame(this.start))) { dates.push(format ? date.format(format) : date); count++; } if (count >= num) break; } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_b && !_b.done && (_c = _a.return)) _c.call(_a); } finally { if (e_3) throw e_3.error; } } return dates; var e_3, _c; }; /** * @internal */ Recur.prototype.addMeasureFunctions = function () { var _this = this; var _loop_1 = function (measureSingle) { var measurePlural = rule_1.Rule.MeasureSingleToPlural[measureSingle]; Recur.prototype[measureSingle] = function (units) { _this.every(units, measurePlural); return _this; }; Recur.prototype[measurePlural] = function (units) { _this.every(units, measurePlural); return _this; }; }; try { for (var _a = __values(Object.keys(rule_1.Rule.MeasureSingleToPlural)), _b = _a.next(); !_b.done; _b = _a.next()) { var measureSingle = _b.value; _loop_1(measureSingle); } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (_b && !_b.done && (_c = _a.return)) _c.call(_a); } finally { if (e_4) throw e_4.error; } } var e_4, _c; }; /** * Private function to see if a date is within range of start/end * @internal */ Recur.prototype.inRange = function (date) { if (this.start && date.isBefore(this.start)) { return false; } else if (this.end && date.isAfter(this.end)) { return false; } else { return true; } }; /** * Private function to check if a date is an exception * @internal */ Recur.prototype.isException = function (date) { try { for (var _a = __values(this.exceptions), _b = _a.next(); !_b.done; _b = _a.next()) { var exception = _b.value; if (moment(exception).isSame(date)) { return true; } } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (_b && !_b.done && (_c = _a.return)) _c.call(_a); } finally { if (e_5) throw e_5.error; } } return false; var e_5, _c; }; /** * Private funtion to see if all rules match * @internal * @hidden */ Recur.prototype.matchAllRules = function (date) { try { for (var _a = __values(this.rules), _b = _a.next(); !_b.done; _b = _a.next()) { var rule = _b.value; if (!rule.match(date)) { return false; } } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (_b && !_b.done && (_c = _a.return)) _c.call(_a); } finally { if (e_6) throw e_6.error; } } return true; var e_6, _c; }; /** * Private funtion to see if all rules match * @internal * @hidden */ Recur.prototype.findNextMatch = function (currentDate) { var nextDate = currentDate.clone().add(1, 'day'); var limit = currentDate.clone().add(this.maximumYears, 'years'); var allRulesMatch = false; while (!allRulesMatch) { // if (nextDate.year() >= currentDate.year() + this.maximumYears) { // throw new RangeError() // } nextDate.subtract(1, 'day'); var nextDates = this.rules.map(function (rule) { return rule.next(nextDate, limit); }); nextDates.sort(function (a, b) { return a.diff(b); }); nextDate = nextDates[nextDates.length - 1]; allRulesMatch = nextDate.isSame(nextDates[0]); } return nextDate; }; /** * Private funtion to see if all rules match * @internal * @hidden */ Recur.prototype.findPreviousMatch = function (currentDate) { var nextDate = currentDate.clone().subtract(1, 'day'); var limit = currentDate.clone().subtract(this.maximumYears, 'years'); var allRulesMatch = false; while (!allRulesMatch) { // if (nextDate.year() <= currentDate.year() - this.maximumYears) { // throw new RangeError() // } nextDate.add(1, 'day'); var nextDates = this.rules.map(function (rule) { return rule.previous(nextDate, limit); }); nextDates.sort(function (a, b) { return b.diff(a); }); nextDate = nextDates[nextDates.length - 1]; allRulesMatch = nextDate.isSame(nextDates[0]); } return nextDate; }; return Recur; }()); exports.Recur = Recur; /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var calendar_1 = __webpack_require__(4); var interval_1 = __webpack_require__(5); var Rule; (function (Rule) { /** * @internal * @hidden */ Rule.MeasureSingleToPlural = { day: 'days', week: 'weeks', month: 'months', year: 'years', dayOfWeek: 'daysOfWeek', dayOfMonth: 'daysOfMonth', weekOfMonth: 'weeksOfMonth', weekOfMonthByDay: 'weeksOfMonthByDay', weekOfYear: 'weeksOfYear', monthOfYear: 'monthsOfYear' }; /** * @internal * @hidden */ function factory(units, measure, start) { var normMeasure = normalizeMeasure(measure); switch (normMeasure) { case 'days': case 'weeks': case 'months': case 'years': return new interval_1.Interval(unitsToArray(units), normMeasure, start); case 'daysOfWeek': case 'daysOfMonth': case 'weeksOfMonth': case 'weeksOfMonthByDay': case 'weeksOfYear': case 'monthsOfYear': return new calendar_1.Calendar(unitsToArray(units), normMeasure); } } Rule.factory = factory; /** * @internal * @hidden */ function unitsToArray(units) { if (units == null) { throw new Error('Units not defined for recurrence rule.'); } else if (Array.isArray(units)) { return units; } else if (typeof units === 'object') { return Object.keys(units); } else if (typeof units === 'number') { return [units]; // tslint:disable-next-line:strict-type-predicates } else if (typeof units === 'string') { return [units]; } else { throw new Error('Provide an array, object, string or number when passing units!'); } } /** * Private function to pluralize measure names for use with dictionaries. * @internal * @hidden */ function normalizeMeasure(measure) { if (typeof measure === 'string') { if (Rule.MeasureSingleToPlural[measure]) { return Rule.MeasureSingleToPlural[measure]; } else { for (var key in Rule.MeasureSingleToPlural) { if (Rule.MeasureSingleToPlural[key] === measure) return measure; } } } throw new Error('Invalid Measure for recurrence: ' + measure); } Rule.normalizeMeasure = normalizeMeasure; })(Rule = exports.Rule || (exports.Rule = {})); /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var moment = __webpack_require__(0); /** * Calendar object for creating and matching calendar-based rules * @internal * @hidden */ var Calendar = /** @class */ (function () { function Calendar(units, measure) { this.measure = measure; this.units = this.normalizeUnits(units); this.range = Calendar.ranges[this.measure].range; this.period = Calendar.ranges[this.measure].period; } Calendar.prototype.match = function (date) { // Get the unit based on the required measure of the date var unit = this.periodUnit(date); // If the unit is in our list, return true, else return false if (this.units.indexOf(unit) !== -1) { return true; } if ((this.units[0] === -1) && (unit === this.periodUnit(moment(date).endOf(this.range)))) { return true; } return false; }; Calendar.prototype.next = function (currentDateIn, limit) { var currentDate = currentDateIn.clone(); // If still within our period, just give the next day if (!this.isLastDayOfPeriod(currentDate)) { var nextDateInPeriod = moment(currentDate).add(1, 'day'); if (this.match(nextDateInPeriod)) return nextDateInPeriod; } while (true) { // Get the next period based on the measure var nextDate = this.nextPeriod(currentDate); if (nextDate) { return nextDate; } else { // No more units found within this range, // bump our range by one and try again. currentDate = this.incrementRange(currentDate, 1); // Check to see if next range starts on a valid period if (this.match(currentDate)) { return currentDate; } if (currentDate.isSameOrAfter(limit)) { throw new RangeError('Recurrence Year limit exceeded.'); } } } }; Calendar.prototype.previous = function (currentDateIn, limit) { var currentDate = currentDateIn.clone(); // If still within our period, just give the next day if (!this.isFirstDayOfPeriod(currentDate)) { var nextDateInPeriod = moment(currentDate).subtract(1, 'day'); if (this.match(nextDateInPeriod)) return nextDateInPeriod; } while (true) { // Get the next period based on the measure var nextDate = this.previousPeriod(currentDate); if (nextDate) { return nextDate; } else { // No more units found within this range, // bump our range by one and try again. currentDate = this.decrementRange(currentDate, 1); // Check to see if next range starts on a valid period if (this.match(currentDate)) { return currentDate; } if (currentDate.isSameOrBefore(limit)) { throw new RangeError('Recurrence Year limit exceeded.'); } } } }; Calendar.prototype.normalizeUnits = function (units) { var _this = this; var low = Calendar.ranges[this.measure].low; var high = Calendar.ranges[this.measure].high; return units.map(function (unitIn) { if (unitIn === 'last') unitIn = -1; if (typeof unitIn !== 'number') { // Convert day/month names to numbers, if needed if (_this.measure === 'daysOfWeek') { unitIn = moment().set('days', unitIn).get('days'); } else if (_this.measure === 'monthsOfYear') { unitIn = moment().set('months', unitIn).get('months'); } else { unitIn = +unitIn; } } if (!Number.isInteger(unitIn)) { throw new TypeError('Invalid calendar unit in recurrence: ' + unitIn); } if ((unitIn < low || unitIn > high) && (unitIn !== -1)) { throw new RangeError('Value should be in range ' + low + ' to ' + high); } return unitIn; }).sort(function (a, b) { return a - b; }); }; Calendar.prototype.periodUnit = function (date, unit) { switch (this.measure) { case 'daysOfWeek': return date.day(unit); case 'daysOfMonth': return date.date(unit); case 'weeksOfMonth': return date.monthWeek(unit); case 'weeksOfMonthByDay': return date.monthWeekByDay(unit); case 'weeksOfYear': return date.week(unit); case 'monthsOfYear': return date.month(unit); } }; Calendar.prototype.nextPeriod = function (date) { var _this = this; // Get the next period based on the measure var currentUnit = this.periodUnit(date); var nextUnit = this.units .map(function (unit) { return unit === -1 ? _this.periodUnit(date.clone().endOf(_this.range)) : unit; }) .find(function (unit) { return unit > currentUnit; }); if (nextUnit !== undefined) { return this.periodUnit(date.clone(), nextUnit).startOf(this.period); } else { // Weeks do not follow orderly periods, e.g. a year can begin and end on week 1 if (this.measure === 'weeksOfYear' && (this.units.indexOf(1) !== -1)) { return date.clone().endOf('year').startOf('week'); } return undefined; } }; Calendar.prototype.previousPeriod = function (date) { var _this = this; // Get the next period based on the measure var currentUnit = this.periodUnit(date); if (this.measure === 'weeksOfYear' && date.month() === 11 && date.week() === 1) currentUnit = 53; var nextUnit = this.units .map(function (unit) { return unit === -1 ? _this.periodUnit(date.clone().endOf(_this.range)) : unit; }) .reverse().find(function (unit) { return unit < currentUnit; }); if (nextUnit !== undefined) { if (this.measure === 'weeksOfYear' && currentUnit === 53) date.week(0); return this.periodUnit(date.clone(), nextUnit).endOf(this.period); } else { // Weeks do not follow orderly periods, e.g. a year can begin and end on week 1 if (this.measure === 'weeksOfYear' && this.units.some(function (u) { return 52 >= u && u <= 53; })) { return date.clone().startOf('year').endOf('week'); } return undefined; } }; Calendar.prototype.incrementRange = function (date, count) { return date.add(count, this.range).startOf(this.range); }; Calendar.prototype.decrementRange = function (date, count) { return date.subtract(count, this.range).endOf(this.range); }; Calendar.prototype.isLastDayOfPeriod = function (date) { if (this.measure === 'weeksOfMonthByDay') { return date.monthWeekByDay() !== moment(date).add(1, 'day').monthWeekByDay(); } if (this.period === 'day') { return true; } else { return date.isSame(moment(date).endOf(this.period)); } }; Calendar.prototype.isFirstDayOfPeriod = function (date) { if (this.measure === 'weeksOfMonthByDay') { return date.monthWeekByDay() !== moment(date).subtract(1, 'day').monthWeekByDay(); } if (this.period === 'day') { return true; } else { return date.isSame(moment(date).startOf(this.period)); } }; Calendar.ranges = { daysOfWeek: { period: 'day', range: 'week', low: 0, high: 6 }, daysOfMonth: { period: 'day', range: 'month', low: 1, high: 31 }, weeksOfMonth: { period: 'week', range: 'month', low: 0, high: 4 }, weeksOfMonthByDay: { period: 'week', range: 'month', low: 0, high: 4 }, weeksOfYear: { period: 'week', range: 'year', low: 1, high: 53 }, monthsOfYear: { period: 'month', range: 'year', low: 0, high: 11 } }; return Calendar; }()); exports.Calendar = Calendar; /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; if (m) return m.call(o); return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; }; Object.defineProperty(exports, "__esModule", { value: true }); /** * Interval object for creating and matching interval-based rules * @internal * @hidden */ var Interval = /** @class */ (function () { function Interval(units, measure, start) { if (!start) { throw new Error('Must have a start date set to set an interval!'); } this.start = start.clone(); this.measure = measure; this.units = this.normalizeUnits(units); } Interval.prototype.match = function (date) { var precise = this.measure !== 'days'; var diff = Math.abs(this.start.diff(date, this.measure, precise)); try { // Check to see if any of the units provided match the date for (var _a = __values(this.units), _b = _a.next(); !_b.done; _b = _a.next()) { var unit = _b.value; // If the units divide evenly into the difference, we have a match if ((diff % unit) === 0) { return true; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_b && !_b.done && (_c = _a.return)) _c.call(_a); } finally { if (e_1) throw e_1.error; } } return false; var e_1, _c; }; Interval.prototype.next = function (currentDate) { // let precise = this.measure !== 'days' // Get the multiple of the start var diff = currentDate.diff(this.start, this.measure); // Find the next muliple for each unit var multiples = this.units.map(function (unit) { return (Math.floor(diff / unit) + 1) * unit; }); multiples.sort(function (a, b) { return a - b; }); return this.start.clone().add(multiples[0], this.measure); }; Interval.prototype.previous = function (currentDate) { // let precise = this.measure !== 'days' // Get the multiple of the start var diff = this.start.diff(currentDate, this.measure); // Find the next muliple for each unit var multiples = this.units.map(function (unit) { return (Math.floor(diff / unit) + 1) * unit; }); multiples.sort(function (a, b) { return b - a; }); return this.start.clone().subtract(multiples[0], this.measure); }; Interval.prototype.normalizeUnits = function (units) { // Make sure all of the units are integers greater than 0. return units.map(function (unit) { unit = +unit; if (unit <= 0) { throw new Error('Intervals must be greater than zero.'); } if (!Number.isInteger(unit)) { throw new Error('Intervals must be integers.'); } return unit; }).sort(function (a, b) { return a - b; }); }; return Interval; }()); exports.Interval = Interval; /***/ }) /******/ ]); }); //# sourceMappingURL=moment-recur-ts.js.map