/ajax/libs/later/1.2.0/later.js
https://gitlab.com/Mirros/cdnjs · JavaScript · 1480 lines · 1464 code · 16 blank · 0 comment · 295 complexity · 5c30f2c601c53e7db912e2d1fd1df1a0 MD5 · raw file
- later = function() {
- "use strict";
- var later = {
- version: "1.2.0"
- };
- if (!Array.prototype.indexOf) {
- Array.prototype.indexOf = function(searchElement) {
- "use strict";
- if (this == null) {
- throw new TypeError();
- }
- var t = Object(this);
- var len = t.length >>> 0;
- if (len === 0) {
- return -1;
- }
- var n = 0;
- if (arguments.length > 1) {
- n = Number(arguments[1]);
- if (n != n) {
- n = 0;
- } else if (n != 0 && n != Infinity && n != -Infinity) {
- n = (n > 0 || -1) * Math.floor(Math.abs(n));
- }
- }
- if (n >= len) {
- return -1;
- }
- var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
- for (;k < len; k++) {
- if (k in t && t[k] === searchElement) {
- return k;
- }
- }
- return -1;
- };
- }
- if (!String.prototype.trim) {
- String.prototype.trim = function() {
- return this.replace(/^\s+|\s+$/g, "");
- };
- }
- later.array = {};
- later.array.sort = function(arr, zeroIsLast) {
- arr.sort(function(a, b) {
- return +a - +b;
- });
- if (zeroIsLast && arr[0] === 0) {
- arr.push(arr.shift());
- }
- };
- later.array.next = function(val, values, extent) {
- var cur, zeroIsLargest = extent[0] !== 0, nextIdx = 0;
- for (var i = values.length - 1; i > -1; --i) {
- cur = values[i];
- if (cur === val) {
- return cur;
- }
- if (cur > val || cur === 0 && zeroIsLargest && extent[1] > val) {
- nextIdx = i;
- continue;
- }
- break;
- }
- return values[nextIdx];
- };
- later.array.nextInvalid = function(val, values, extent) {
- var min = extent[0], max = extent[1], len = values.length, zeroVal = values[len - 1] === 0 && min !== 0 ? max : 0, next = val, i = values.indexOf(val), start = next;
- while (next === (values[i] || zeroVal)) {
- next++;
- if (next > max) {
- next = min;
- }
- i++;
- if (i === len) {
- i = 0;
- }
- if (next === start) {
- return undefined;
- }
- }
- return next;
- };
- later.array.prev = function(val, values, extent) {
- var cur, len = values.length, zeroIsLargest = extent[0] !== 0, prevIdx = len - 1;
- for (var i = 0; i < len; i++) {
- cur = values[i];
- if (cur === val) {
- return cur;
- }
- if (cur < val || cur === 0 && zeroIsLargest && extent[1] < val) {
- prevIdx = i;
- continue;
- }
- break;
- }
- return values[prevIdx];
- };
- later.array.prevInvalid = function(val, values, extent) {
- var min = extent[0], max = extent[1], len = values.length, zeroVal = values[len - 1] === 0 && min !== 0 ? max : 0, next = val, i = values.indexOf(val), start = next;
- while (next === (values[i] || zeroVal)) {
- next--;
- if (next < min) {
- next = max;
- }
- i--;
- if (i === -1) {
- i = len - 1;
- }
- if (next === start) {
- return undefined;
- }
- }
- return next;
- };
- later.day = later.D = {
- name: "day",
- range: 86400,
- val: function(d) {
- return d.D || (d.D = later.date.getDate.call(d));
- },
- isValid: function(d, val) {
- return later.D.val(d) === (val || later.D.extent(d)[1]);
- },
- extent: function(d) {
- if (d.DExtent) return d.DExtent;
- var month = later.M.val(d), max = later.DAYS_IN_MONTH[month - 1];
- if (month === 2 && later.dy.extent(d)[1] === 366) {
- max = max + 1;
- }
- return d.DExtent = [ 1, max ];
- },
- start: function(d) {
- return d.DStart || (d.DStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d)));
- },
- end: function(d) {
- return d.DEnd || (d.DEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d)));
- },
- next: function(d, val) {
- val = val > later.D.extent(d)[1] ? 1 : val;
- var month = later.date.nextRollover(d, val, later.D, later.M), DMax = later.D.extent(month)[1];
- val = val > DMax ? 1 : val || DMax;
- return later.date.next(later.Y.val(month), later.M.val(month), val);
- },
- prev: function(d, val) {
- var month = later.date.prevRollover(d, val, later.D, later.M), DMax = later.D.extent(month)[1];
- return later.date.prev(later.Y.val(month), later.M.val(month), val > DMax ? DMax : val || DMax);
- }
- };
- later.dayOfWeekCount = later.dc = {
- name: "day of week count",
- range: 604800,
- val: function(d) {
- return d.dc || (d.dc = Math.floor((later.D.val(d) - 1) / 7) + 1);
- },
- isValid: function(d, val) {
- return later.dc.val(d) === val || val === 0 && later.D.val(d) > later.D.extent(d)[1] - 7;
- },
- extent: function(d) {
- return d.dcExtent || (d.dcExtent = [ 1, Math.ceil(later.D.extent(d)[1] / 7) ]);
- },
- start: function(d) {
- return d.dcStart || (d.dcStart = later.date.next(later.Y.val(d), later.M.val(d), Math.max(1, (later.dc.val(d) - 1) * 7 + 1 || 1)));
- },
- end: function(d) {
- return d.dcEnd || (d.dcEnd = later.date.prev(later.Y.val(d), later.M.val(d), Math.min(later.dc.val(d) * 7, later.D.extent(d)[1])));
- },
- next: function(d, val) {
- val = val > later.dc.extent(d)[1] ? 1 : val;
- var month = later.date.nextRollover(d, val, later.dc, later.M), dcMax = later.dc.extent(month)[1];
- val = val > dcMax ? 1 : val;
- var next = later.date.next(later.Y.val(month), later.M.val(month), val === 0 ? later.D.extent(month)[1] - 6 : 1 + 7 * (val - 1));
- if (next.getTime() <= d.getTime()) {
- month = later.M.next(d, later.M.val(d) + 1);
- return later.date.next(later.Y.val(month), later.M.val(month), val === 0 ? later.D.extent(month)[1] - 6 : 1 + 7 * (val - 1));
- }
- return next;
- },
- prev: function(d, val) {
- var month = later.date.prevRollover(d, val, later.dc, later.M), dcMax = later.dc.extent(month)[1];
- val = val > dcMax ? dcMax : val || dcMax;
- return later.dc.end(later.date.prev(later.Y.val(month), later.M.val(month), 1 + 7 * (val - 1)));
- }
- };
- later.dayOfWeek = later.dw = later.d = {
- name: "day of week",
- range: 86400,
- val: function(d) {
- return d.dw || (d.dw = later.date.getDay.call(d) + 1);
- },
- isValid: function(d, val) {
- return later.dw.val(d) === (val || 7);
- },
- extent: function() {
- return [ 1, 7 ];
- },
- start: function(d) {
- return later.D.start(d);
- },
- end: function(d) {
- return later.D.end(d);
- },
- next: function(d, val) {
- val = val > 7 ? 1 : val || 7;
- return later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val - later.dw.val(d)) + (val <= later.dw.val(d) ? 7 : 0));
- },
- prev: function(d, val) {
- val = val > 7 ? 7 : val || 7;
- return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d) + (val - later.dw.val(d)) + (val >= later.dw.val(d) ? -7 : 0));
- }
- };
- later.dayOfYear = later.dy = {
- name: "day of year",
- range: 86400,
- val: function(d) {
- return d.dy || (d.dy = Math.ceil(1 + (later.D.start(d).getTime() - later.Y.start(d).getTime()) / later.DAY));
- },
- isValid: function(d, val) {
- return later.dy.val(d) === (val || later.dy.extent(d)[1]);
- },
- extent: function(d) {
- var year = later.Y.val(d);
- return d.dyExtent || (d.dyExtent = [ 1, year % 4 ? 365 : 366 ]);
- },
- start: function(d) {
- return later.D.start(d);
- },
- end: function(d) {
- return later.D.end(d);
- },
- next: function(d, val) {
- val = val > later.dy.extent(d)[1] ? 1 : val;
- var year = later.date.nextRollover(d, val, later.dy, later.Y), dyMax = later.dy.extent(year)[1];
- val = val > dyMax ? 1 : val || dyMax;
- return later.date.next(later.Y.val(year), later.M.val(year), val);
- },
- prev: function(d, val) {
- var year = later.date.prevRollover(d, val, later.dy, later.Y), dyMax = later.dy.extent(year)[1];
- val = val > dyMax ? dyMax : val || dyMax;
- return later.date.prev(later.Y.val(year), later.M.val(year), val);
- }
- };
- later.hour = later.h = {
- name: "hour",
- range: 3600,
- val: function(d) {
- return d.h || (d.h = later.date.getHour.call(d));
- },
- isValid: function(d, val) {
- return later.h.val(d) === val;
- },
- extent: function() {
- return [ 0, 23 ];
- },
- start: function(d) {
- return d.hStart || (d.hStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d)));
- },
- end: function(d) {
- return d.hEnd || (d.hEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d)));
- },
- next: function(d, val) {
- val = val > 23 ? 0 : val;
- var next = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val <= later.h.val(d) ? 1 : 0), val);
- if (!later.date.isUTC && next.getTime() <= d.getTime()) {
- next = later.date.next(later.Y.val(next), later.M.val(next), later.D.val(next), val + 1);
- }
- return next;
- },
- prev: function(d, val) {
- val = val > 23 ? 23 : val;
- return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d) + (val >= later.h.val(d) ? -1 : 0), val);
- }
- };
- later.minute = later.m = {
- name: "minute",
- range: 60,
- val: function(d) {
- return d.m || (d.m = later.date.getMin.call(d));
- },
- isValid: function(d, val) {
- return later.m.val(d) === val;
- },
- extent: function(d) {
- return [ 0, 59 ];
- },
- start: function(d) {
- return d.mStart || (d.mStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d), later.m.val(d)));
- },
- end: function(d) {
- return d.mEnd || (d.mEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d), later.m.val(d)));
- },
- next: function(d, val) {
- var m = later.m.val(d), s = later.s.val(d), inc = val > 59 ? 60 - m : val <= m ? 60 - m + val : val - m, next = new Date(d.getTime() + inc * later.MIN - s * later.SEC);
- if (!later.date.isUTC && next.getTime() <= d.getTime()) {
- next = new Date(d.getTime() + (inc + 120) * later.MIN - s * later.SEC);
- }
- return next;
- },
- prev: function(d, val) {
- val = val > 59 ? 59 : val;
- return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d) + (val >= later.m.val(d) ? -1 : 0), val);
- }
- };
- later.month = later.M = {
- name: "month",
- range: 2629740,
- val: function(d) {
- return d.M || (d.M = later.date.getMonth.call(d) + 1);
- },
- isValid: function(d, val) {
- return later.M.val(d) === (val || 12);
- },
- extent: function() {
- return [ 1, 12 ];
- },
- start: function(d) {
- return d.MStart || (d.MStart = later.date.next(later.Y.val(d), later.M.val(d)));
- },
- end: function(d) {
- return d.MEnd || (d.MEnd = later.date.prev(later.Y.val(d), later.M.val(d)));
- },
- next: function(d, val) {
- val = val > 12 ? 1 : val || 12;
- return later.date.next(later.Y.val(d) + (val > later.M.val(d) ? 0 : 1), val);
- },
- prev: function(d, val) {
- val = val > 12 ? 12 : val || 12;
- return later.date.prev(later.Y.val(d) - (val >= later.M.val(d) ? 1 : 0), val);
- }
- };
- later.second = later.s = {
- name: "second",
- range: 1,
- val: function(d) {
- return d.s || (d.s = later.date.getSec.call(d));
- },
- isValid: function(d, val) {
- return later.s.val(d) === val;
- },
- extent: function() {
- return [ 0, 59 ];
- },
- start: function(d) {
- return d;
- },
- end: function(d) {
- return d;
- },
- next: function(d, val) {
- var s = later.s.val(d), inc = val > 59 ? 60 - s : val <= s ? 60 - s + val : val - s, next = new Date(d.getTime() + inc * later.SEC);
- if (!later.date.isUTC && next.getTime() <= d.getTime()) {
- next = new Date(d.getTime() + (inc + 7200) * later.SEC);
- }
- return next;
- },
- prev: function(d, val, cache) {
- val = val > 59 ? 59 : val;
- return later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d), later.h.val(d), later.m.val(d) + (val >= later.s.val(d) ? -1 : 0), val);
- }
- };
- later.time = later.t = {
- name: "time",
- range: 1,
- val: function(d) {
- return d.t || (d.t = later.h.val(d) * 3600 + later.m.val(d) * 60 + later.s.val(d));
- },
- isValid: function(d, val) {
- return later.t.val(d) === val;
- },
- extent: function() {
- return [ 0, 86399 ];
- },
- start: function(d) {
- return d;
- },
- end: function(d) {
- return d;
- },
- next: function(d, val) {
- val = val > 86399 ? 0 : val;
- var next = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val <= later.t.val(d) ? 1 : 0), 0, 0, val);
- if (!later.date.isUTC && next.getTime() < d.getTime()) {
- next = later.date.next(later.Y.val(next), later.M.val(next), later.D.val(next), later.h.val(next), later.m.val(next), val + 7200);
- }
- return next;
- },
- prev: function(d, val) {
- val = val > 86399 ? 86399 : val;
- return later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) + (val >= later.t.val(d) ? -1 : 0), 0, 0, val);
- }
- };
- later.weekOfMonth = later.wm = {
- name: "week of month",
- range: 604800,
- val: function(d) {
- return d.wm || (d.wm = (later.D.val(d) + (later.dw.val(later.M.start(d)) - 1) + (7 - later.dw.val(d))) / 7);
- },
- isValid: function(d, val) {
- return later.wm.val(d) === (val || later.wm.extent(d)[1]);
- },
- extent: function(d) {
- return d.wmExtent || (d.wmExtent = [ 1, (later.D.extent(d)[1] + (later.dw.val(later.M.start(d)) - 1) + (7 - later.dw.val(later.M.end(d)))) / 7 ]);
- },
- start: function(d) {
- return d.wmStart || (d.wmStart = later.date.next(later.Y.val(d), later.M.val(d), Math.max(later.D.val(d) - later.dw.val(d) + 1, 1)));
- },
- end: function(d) {
- return d.wmEnd || (d.wmEnd = later.date.prev(later.Y.val(d), later.M.val(d), Math.min(later.D.val(d) + (7 - later.dw.val(d)), later.D.extent(d)[1])));
- },
- next: function(d, val) {
- val = val > later.wm.extent(d)[1] ? 1 : val;
- var month = later.date.nextRollover(d, val, later.wm, later.M), wmMax = later.wm.extent(month)[1];
- val = val > wmMax ? 1 : val || wmMax;
- return later.date.next(later.Y.val(month), later.M.val(month), Math.max(1, (val - 1) * 7 - (later.dw.val(month) - 2)));
- },
- prev: function(d, val) {
- var month = later.date.prevRollover(d, val, later.wm, later.M), wmMax = later.wm.extent(month)[1];
- val = val > wmMax ? wmMax : val || wmMax;
- return later.wm.end(later.date.next(later.Y.val(month), later.M.val(month), Math.max(1, (val - 1) * 7 - (later.dw.val(month) - 2))));
- }
- };
- later.weekOfYear = later.wy = {
- name: "week of year (ISO)",
- range: 604800,
- val: function(d) {
- if (d.wy) return d.wy;
- var wThur = later.dw.next(later.wy.start(d), 5), YThur = later.dw.next(later.Y.prev(wThur, later.Y.val(wThur) - 1), 5);
- return d.wy = 1 + Math.ceil((wThur.getTime() - YThur.getTime()) / later.WEEK);
- },
- isValid: function(d, val) {
- return later.wy.val(d) === (val || later.wy.extent(d)[1]);
- },
- extent: function(d) {
- if (d.wyExtent) return d.wyExtent;
- var year = later.dw.next(later.wy.start(d), 5), dwFirst = later.dw.val(later.Y.start(year)), dwLast = later.dw.val(later.Y.end(year));
- return d.wyExtent = [ 1, dwFirst === 5 || dwLast === 5 ? 53 : 52 ];
- },
- start: function(d) {
- return d.wyStart || (d.wyStart = later.date.next(later.Y.val(d), later.M.val(d), later.D.val(d) - (later.dw.val(d) > 1 ? later.dw.val(d) - 2 : 6)));
- },
- end: function(d) {
- return d.wyEnd || (d.wyEnd = later.date.prev(later.Y.val(d), later.M.val(d), later.D.val(d) + (later.dw.val(d) > 1 ? 8 - later.dw.val(d) : 0)));
- },
- next: function(d, val) {
- val = val > later.wy.extent(d)[1] ? 1 : val;
- var wyThur = later.dw.next(later.wy.start(d), 5), year = later.date.nextRollover(wyThur, val, later.wy, later.Y);
- if (later.wy.val(year) !== 1) {
- year = later.dw.next(year, 2);
- }
- var wyMax = later.wy.extent(year)[1], wyStart = later.wy.start(year);
- val = val > wyMax ? 1 : val || wyMax;
- return later.date.next(later.Y.val(wyStart), later.M.val(wyStart), later.D.val(wyStart) + 7 * (val - 1));
- },
- prev: function(d, val) {
- var wyThur = later.dw.next(later.wy.start(d), 5), year = later.date.prevRollover(wyThur, val, later.wy, later.Y);
- if (later.wy.val(year) !== 1) {
- year = later.dw.next(year, 2);
- }
- var wyMax = later.wy.extent(year)[1], wyEnd = later.wy.end(year);
- val = val > wyMax ? wyMax : val || wyMax;
- return later.wy.end(later.date.next(later.Y.val(wyEnd), later.M.val(wyEnd), later.D.val(wyEnd) + 7 * (val - 1)));
- }
- };
- later.year = later.Y = {
- name: "year",
- range: 31556900,
- val: function(d) {
- return d.Y || (d.Y = later.date.getYear.call(d));
- },
- isValid: function(d, val) {
- return later.Y.val(d) === val;
- },
- extent: function() {
- return [ 1970, 2099 ];
- },
- start: function(d) {
- return d.YStart || (d.YStart = later.date.next(later.Y.val(d)));
- },
- end: function(d) {
- return d.YEnd || (d.YEnd = later.date.prev(later.Y.val(d)));
- },
- next: function(d, val) {
- return val > later.Y.val(d) && val <= later.Y.extent()[1] ? later.date.next(val) : later.NEVER;
- },
- prev: function(d, val) {
- return val < later.Y.val(d) && val >= later.Y.extent()[0] ? later.date.prev(val) : later.NEVER;
- }
- };
- later.fullDate = later.fd = {
- name: "full date",
- range: 1,
- val: function(d) {
- return d.fd || (d.fd = d.getTime());
- },
- isValid: function(d, val) {
- return later.fd.val(d) === val;
- },
- extent: function() {
- return [ 0, 3250368e7 ];
- },
- start: function(d) {
- return d;
- },
- end: function(d) {
- return d;
- },
- next: function(d, val) {
- return later.fd.val(d) < val ? new Date(val) : later.NEVER;
- },
- prev: function(d, val) {
- return later.fd.val(d) > val ? new Date(val) : later.NEVER;
- }
- };
- later.modifier = {};
- later.modifier.after = later.modifier.a = function(constraint, values) {
- var value = values[0];
- return {
- name: "after " + constraint.name,
- range: (constraint.extent(new Date())[1] - value) * constraint.range,
- val: constraint.val,
- isValid: function(d, val) {
- return this.val(d) >= value;
- },
- extent: constraint.extent,
- start: constraint.start,
- end: constraint.end,
- next: function(startDate, val) {
- if (val != value) val = constraint.extent(startDate)[0];
- return constraint.next(startDate, val);
- },
- prev: function(startDate, val) {
- val = val === value ? constraint.extent(startDate)[1] : value - 1;
- return constraint.prev(startDate, val);
- }
- };
- };
- later.modifier.before = later.modifier.b = function(constraint, values) {
- var value = values[values.length - 1];
- return {
- name: "before " + constraint.name,
- range: constraint.range * (value - 1),
- val: constraint.val,
- isValid: function(d, val) {
- return this.val(d) < value;
- },
- extent: constraint.extent,
- start: constraint.start,
- end: constraint.end,
- next: function(startDate, val) {
- val = val === value ? constraint.extent(startDate)[0] : value;
- return constraint.next(startDate, val);
- },
- prev: function(startDate, val) {
- val = val === value ? value - 1 : constraint.extent(startDate)[1];
- return constraint.prev(startDate, val);
- }
- };
- };
- later.compile = function(schedDef) {
- var constraints = [], constraintsLen = 0, tickConstraint;
- for (var key in schedDef) {
- var nameParts = key.split("_"), name = nameParts[0], mod = nameParts[1], vals = schedDef[key], constraint = mod ? later.modifier[mod](later[name], vals) : later[name];
- constraints.push({
- constraint: constraint,
- vals: vals
- });
- constraintsLen++;
- }
- constraints.sort(function(a, b) {
- var ra = a.constraint.range, rb = b.constraint.range;
- return rb < ra ? -1 : rb > ra ? 1 : 0;
- });
- tickConstraint = constraints[constraintsLen - 1].constraint;
- function compareFn(dir) {
- return dir === "next" ? function(a, b) {
- return a.getTime() > b.getTime();
- } : function(a, b) {
- return b.getTime() > a.getTime();
- };
- }
- return {
- start: function(dir, startDate) {
- var next = startDate, nextVal = later.array[dir], maxAttempts = 1e3, done;
- while (maxAttempts-- && !done && next) {
- done = true;
- for (var i = 0; i < constraintsLen; i++) {
- var constraint = constraints[i].constraint, curVal = constraint.val(next), extent = constraint.extent(next), newVal = nextVal(curVal, constraints[i].vals, extent);
- if (!constraint.isValid(next, newVal)) {
- next = constraint[dir](next, newVal);
- done = false;
- break;
- }
- }
- }
- if (next !== later.NEVER) {
- next = dir === "next" ? tickConstraint.start(next) : tickConstraint.end(next);
- }
- return next;
- },
- end: function(dir, startDate) {
- var result, nextVal = later.array[dir + "Invalid"], compare = compareFn(dir);
- for (var i = constraintsLen - 1; i >= 0; i--) {
- var constraint = constraints[i].constraint, curVal = constraint.val(startDate), extent = constraint.extent(startDate), newVal = nextVal(curVal, constraints[i].vals, extent), next;
- if (newVal !== undefined) {
- next = constraint[dir](startDate, newVal);
- if (next && (!result || compare(result, next))) {
- result = next;
- }
- }
- }
- return result;
- },
- tick: function(dir, date) {
- return new Date(dir === "next" ? tickConstraint.end(date).getTime() + later.SEC : tickConstraint.start(date).getTime() - later.SEC);
- },
- tickStart: function(date) {
- return tickConstraint.start(date);
- }
- };
- };
- later.schedule = function(sched) {
- if (!sched) throw new Error("Missing schedule definition.");
- if (!sched.schedules) throw new Error("Definition must include at least one schedule.");
- var schedules = [], schedulesLen = sched.schedules.length, exceptions = [], exceptionsLen = sched.exceptions ? sched.exceptions.length : 0;
- for (var i = 0; i < schedulesLen; i++) {
- schedules.push(later.compile(sched.schedules[i]));
- }
- for (var j = 0; j < exceptionsLen; j++) {
- exceptions.push(later.compile(sched.exceptions[j]));
- }
- function getInstances(dir, count, startDate, endDate, isRange) {
- var compare = compareFn(dir), loopCount = count, maxAttempts = 1e3, schedStarts = [], exceptStarts = [], next, end, results = [], isForward = dir === "next", lastResult, rStart = isForward ? 0 : 1, rEnd = isForward ? 1 : 0;
- startDate = startDate ? new Date(startDate) : new Date();
- if (!startDate || !startDate.getTime()) throw new Error("Invalid start date.");
- setNextStarts(dir, schedules, schedStarts, startDate);
- setRangeStarts(dir, exceptions, exceptStarts, startDate);
- while (maxAttempts-- && loopCount && (next = findNext(schedStarts, compare))) {
- if (endDate && compare(next, endDate)) {
- break;
- }
- if (exceptionsLen) {
- updateRangeStarts(dir, exceptions, exceptStarts, next);
- if (end = calcRangeOverlap(dir, exceptStarts, next)) {
- updateNextStarts(dir, schedules, schedStarts, end);
- continue;
- }
- }
- if (isRange) {
- var maxEndDate = calcMaxEndDate(exceptStarts, compare);
- end = calcEnd(dir, schedules, schedStarts, next, maxEndDate);
- var r = isForward ? [ new Date(Math.max(startDate, next)), end ? new Date(endDate ? Math.min(end, endDate) : end) : undefined ] : [ end ? new Date(endDate ? Math.max(endDate, end.getTime() + later.SEC) : end.getTime() + later.SEC) : undefined, new Date(Math.min(startDate, next.getTime() + later.SEC)) ];
- if (lastResult && r[rStart].getTime() === lastResult[rEnd].getTime()) {
- lastResult[rEnd] = r[rEnd];
- loopCount++;
- } else {
- lastResult = r;
- results.push(lastResult);
- }
- if (!end) break;
- updateNextStarts(dir, schedules, schedStarts, end);
- } else {
- results.push(isForward ? new Date(Math.max(startDate, next)) : getStart(schedules, schedStarts, next, endDate));
- tickStarts(dir, schedules, schedStarts, next);
- }
- loopCount--;
- }
- for (var i = 0, len = results.length; i < len; i++) {
- var result = results[i];
- results[i] = Object.prototype.toString.call(result) === "[object Array]" ? [ cleanDate(result[0]), cleanDate(result[1]) ] : cleanDate(result);
- }
- return results.length === 0 ? later.NEVER : count === 1 ? results[0] : results;
- }
- function cleanDate(d) {
- if (d instanceof Date && !isNaN(d.valueOf())) {
- return new Date(d);
- }
- return undefined;
- }
- function setNextStarts(dir, schedArr, startsArr, startDate) {
- for (var i = 0, len = schedArr.length; i < len; i++) {
- startsArr[i] = schedArr[i].start(dir, startDate);
- }
- }
- function updateNextStarts(dir, schedArr, startsArr, startDate) {
- var compare = compareFn(dir);
- for (var i = 0, len = schedArr.length; i < len; i++) {
- if (startsArr[i] && !compare(startsArr[i], startDate)) {
- startsArr[i] = schedArr[i].start(dir, startDate);
- }
- }
- }
- function setRangeStarts(dir, schedArr, rangesArr, startDate) {
- var compare = compareFn(dir);
- for (var i = 0, len = schedArr.length; i < len; i++) {
- var nextStart = schedArr[i].start(dir, startDate);
- if (!nextStart) {
- rangesArr[i] = later.NEVER;
- } else {
- rangesArr[i] = [ nextStart, schedArr[i].end(dir, nextStart) ];
- }
- }
- }
- function updateRangeStarts(dir, schedArr, rangesArr, startDate) {
- var compare = compareFn(dir);
- for (var i = 0, len = schedArr.length; i < len; i++) {
- if (rangesArr[i] && !compare(rangesArr[i][0], startDate)) {
- var nextStart = schedArr[i].start(dir, startDate);
- if (!nextStart) {
- rangesArr[i] = later.NEVER;
- } else {
- rangesArr[i] = [ nextStart, schedArr[i].end(dir, nextStart) ];
- }
- }
- }
- }
- function tickStarts(dir, schedArr, startsArr, startDate) {
- for (var i = 0, len = schedArr.length; i < len; i++) {
- if (startsArr[i] && startsArr[i].getTime() === startDate.getTime()) {
- startsArr[i] = schedArr[i].start(dir, schedArr[i].tick(dir, startDate));
- }
- }
- }
- function getStart(schedArr, startsArr, startDate, minEndDate) {
- var result;
- for (var i = 0, len = startsArr.length; i < len; i++) {
- if (startsArr[i] && startsArr[i].getTime() === startDate.getTime()) {
- var start = schedArr[i].tickStart(startDate);
- if (minEndDate && start < minEndDate) {
- return minEndDate;
- }
- if (!result || start > result) {
- result = start;
- }
- }
- }
- return result;
- }
- function calcRangeOverlap(dir, rangesArr, startDate) {
- var compare = compareFn(dir), result;
- for (var i = 0, len = rangesArr.length; i < len; i++) {
- var range = rangesArr[i];
- if (range && !compare(range[0], startDate) && (!range[1] || compare(range[1], startDate))) {
- if (!result || compare(range[1], result)) {
- result = range[1];
- }
- }
- }
- return result;
- }
- function calcMaxEndDate(exceptsArr, compare) {
- var result;
- for (var i = 0, len = exceptsArr.length; i < len; i++) {
- if (exceptsArr[i] && (!result || compare(result, exceptsArr[i][0]))) {
- result = exceptsArr[i][0];
- }
- }
- return result;
- }
- function calcEnd(dir, schedArr, startsArr, startDate, maxEndDate) {
- var compare = compareFn(dir), result;
- for (var i = 0, len = schedArr.length; i < len; i++) {
- var start = startsArr[i];
- if (start && start.getTime() === startDate.getTime()) {
- var end = schedArr[i].end(dir, start);
- if (maxEndDate && (!end || compare(end, maxEndDate))) {
- return maxEndDate;
- }
- if (!result || compare(end, result)) {
- result = end;
- }
- }
- }
- return result;
- }
- function compareFn(dir) {
- return dir === "next" ? function(a, b) {
- return !b || a.getTime() > b.getTime();
- } : function(a, b) {
- return !a || b.getTime() > a.getTime();
- };
- }
- function findNext(arr, compare) {
- var next = arr[0];
- for (var i = 1, len = arr.length; i < len; i++) {
- if (arr[i] && compare(next, arr[i])) {
- next = arr[i];
- }
- }
- return next;
- }
- return {
- isValid: function(d) {
- return getInstances("next", 1, d, d) !== later.NEVER;
- },
- next: function(count, startDate, endDate) {
- return getInstances("next", count || 1, startDate, endDate);
- },
- prev: function(count, startDate, endDate) {
- return getInstances("prev", count || 1, startDate, endDate);
- },
- nextRange: function(count, startDate, endDate) {
- return getInstances("next", count || 1, startDate, endDate, true);
- },
- prevRange: function(count, startDate, endDate) {
- return getInstances("prev", count || 1, startDate, endDate, true);
- }
- };
- };
- later.setTimeout = function(fn, sched) {
- var s = later.schedule(sched), t;
- if (fn) {
- scheduleTimeout();
- }
- function scheduleTimeout() {
- var now = Date.now(), next = s.next(2, now);
- if (!next[0]) {
- t = undefined;
- return;
- }
- var diff = next[0].getTime() - now;
- if (diff < 1e3) {
- diff = next[1] ? next[1].getTime() - now : 1e3;
- }
- if (diff < 2147483647) {
- t = setTimeout(fn, diff);
- } else {
- t = setTimeout(scheduleTimeout, 2147483647);
- }
- }
- return {
- isDone: function() {
- return !t;
- },
- clear: function() {
- clearTimeout(t);
- }
- };
- };
- later.setInterval = function(fn, sched) {
- if (!fn) {
- return;
- }
- var t = later.setTimeout(scheduleTimeout, sched), done = t.isDone();
- function scheduleTimeout() {
- if (!done) {
- fn();
- t = later.setTimeout(scheduleTimeout, sched);
- }
- }
- return {
- isDone: function() {
- return t.isDone();
- },
- clear: function() {
- done = true;
- t.clear();
- }
- };
- };
- later.date = {};
- later.date.timezone = function(useLocalTime) {
- later.date.build = useLocalTime ? function(Y, M, D, h, m, s) {
- return new Date(Y, M, D, h, m, s);
- } : function(Y, M, D, h, m, s) {
- return new Date(Date.UTC(Y, M, D, h, m, s));
- };
- var get = useLocalTime ? "get" : "getUTC", d = Date.prototype;
- later.date.getYear = d[get + "FullYear"];
- later.date.getMonth = d[get + "Month"];
- later.date.getDate = d[get + "Date"];
- later.date.getDay = d[get + "Day"];
- later.date.getHour = d[get + "Hours"];
- later.date.getMin = d[get + "Minutes"];
- later.date.getSec = d[get + "Seconds"];
- later.date.isUTC = !useLocalTime;
- };
- later.date.UTC = function() {
- later.date.timezone(false);
- };
- later.date.localTime = function() {
- later.date.timezone(true);
- };
- later.date.UTC();
- later.SEC = 1e3;
- later.MIN = later.SEC * 60;
- later.HOUR = later.MIN * 60;
- later.DAY = later.HOUR * 24;
- later.WEEK = later.DAY * 7;
- later.DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
- later.NEVER = 0;
- later.date.next = function(Y, M, D, h, m, s) {
- return later.date.build(Y, M !== undefined ? M - 1 : 0, D !== undefined ? D : 1, h || 0, m || 0, s || 0);
- };
- later.date.nextRollover = function(d, val, constraint, period) {
- var cur = constraint.val(d), max = constraint.extent(d)[1];
- return (val || max) <= cur || val > max ? new Date(period.end(d).getTime() + later.SEC) : period.start(d);
- };
- later.date.prev = function(Y, M, D, h, m, s) {
- var len = arguments.length;
- M = len < 2 ? 11 : M - 1;
- D = len < 3 ? later.D.extent(later.date.next(Y, M + 1))[1] : D;
- h = len < 4 ? 23 : h;
- m = len < 5 ? 59 : m;
- s = len < 6 ? 59 : s;
- return later.date.build(Y, M, D, h, m, s);
- };
- later.date.prevRollover = function(d, val, constraint, period) {
- var cur = constraint.val(d);
- return val >= cur || !val ? period.start(period.prev(d, period.val(d) - 1)) : period.start(d);
- };
- later.parse = {};
- later.parse.cron = function(expr, hasSeconds) {
- var NAMES = {
- JAN: 1,
- FEB: 2,
- MAR: 3,
- APR: 4,
- MAY: 5,
- JUN: 6,
- JUL: 7,
- AUG: 8,
- SEP: 9,
- OCT: 10,
- NOV: 11,
- DEC: 12,
- SUN: 1,
- MON: 2,
- TUE: 3,
- WED: 4,
- THU: 5,
- FRI: 6,
- SAT: 7
- };
- var REPLACEMENTS = {
- "* * * * * *": "0/1 * * * * *",
- "@YEARLY": "0 0 1 1 *",
- "@ANNUALLY": "0 0 1 1 *",
- "@MONTHLY": "0 0 1 * *",
- "@WEEKLY": "0 0 * * 0",
- "@DAILY": "0 0 * * *",
- "@HOURLY": "0 * * * *"
- };
- var FIELDS = {
- s: [ 0, 0, 59 ],
- m: [ 1, 0, 59 ],
- h: [ 2, 0, 23 ],
- D: [ 3, 1, 31 ],
- M: [ 4, 1, 12 ],
- Y: [ 6, 1970, 2099 ],
- d: [ 5, 1, 7, 1 ]
- };
- function getValue(value, offset, max) {
- return isNaN(value) ? NAMES[value] || null : Math.min(+value + (offset || 0), max || 9999);
- }
- function cloneSchedule(sched) {
- var clone = {}, field;
- for (field in sched) {
- if (field !== "dc" && field !== "d") {
- clone[field] = sched[field].slice(0);
- }
- }
- return clone;
- }
- function add(sched, name, min, max, inc) {
- var i = min;
- if (!sched[name]) {
- sched[name] = [];
- }
- while (i <= max) {
- if (sched[name].indexOf(i) < 0) {
- sched[name].push(i);
- }
- i += inc || 1;
- }
- sched[name].sort(function(a, b) {
- return a - b;
- });
- }
- function addHash(schedules, curSched, value, hash) {
- if (curSched.d && !curSched.dc || curSched.dc && curSched.dc.indexOf(hash) < 0) {
- schedules.push(cloneSchedule(curSched));
- curSched = schedules[schedules.length - 1];
- }
- add(curSched, "d", value, value);
- add(curSched, "dc", hash, hash);
- }
- function addWeekday(s, curSched, value) {
- var except1 = {}, except2 = {};
- if (value === 1) {
- add(curSched, "D", 1, 3);
- add(curSched, "d", NAMES.MON, NAMES.FRI);
- add(except1, "D", 2, 2);
- add(except1, "d", NAMES.TUE, NAMES.FRI);
- add(except2, "D", 3, 3);
- add(except2, "d", NAMES.TUE, NAMES.FRI);
- } else {
- add(curSched, "D", value - 1, value + 1);
- add(curSched, "d", NAMES.MON, NAMES.FRI);
- add(except1, "D", value - 1, value - 1);
- add(except1, "d", NAMES.MON, NAMES.THU);
- add(except2, "D", value + 1, value + 1);
- add(except2, "d", NAMES.TUE, NAMES.FRI);
- }
- s.exceptions.push(except1);
- s.exceptions.push(except2);
- }
- function addRange(item, curSched, name, min, max, offset) {
- var incSplit = item.split("/"), inc = +incSplit[1], range = incSplit[0];
- if (range !== "*" && range !== "0") {
- var rangeSplit = range.split("-");
- min = getValue(rangeSplit[0], offset, max);
- max = getValue(rangeSplit[1], offset, max) || max;
- }
- add(curSched, name, min, max, inc);
- }
- function parse(item, s, name, min, max, offset) {
- var value, split, schedules = s.schedules, curSched = schedules[schedules.length - 1];
- if (item === "L") {
- item = min - 1;
- }
- if ((value = getValue(item, offset, max)) !== null) {
- add(curSched, name, value, value);
- } else if ((value = getValue(item.replace("W", ""), offset, max)) !== null) {
- addWeekday(s, curSched, value);
- } else if ((value = getValue(item.replace("L", ""), offset, max)) !== null) {
- addHash(schedules, curSched, value, min - 1);
- } else if ((split = item.split("#")).length === 2) {
- value = getValue(split[0], offset, max);
- addHash(schedules, curSched, value, getValue(split[1]));
- } else {
- addRange(item, curSched, name, min, max, offset);
- }
- }
- function isHash(item) {
- return item.indexOf("#") > -1 || item.indexOf("L") > 0;
- }
- function itemSorter(a, b) {
- return isHash(a) && !isHash(b) ? 1 : a - b;
- }
- function parseExpr(expr) {
- var schedule = {
- schedules: [ {} ],
- exceptions: []
- }, components = expr.replace(/(\s)+/g, " ").split(" "), field, f, component, items;
- for (field in FIELDS) {
- f = FIELDS[field];
- component = components[f[0]];
- if (component && component !== "*" && component !== "?") {
- items = component.split(",").sort(itemSorter);
- var i, length = items.length;
- for (i = 0; i < length; i++) {
- parse(items[i], schedule, field, f[1], f[2], f[3]);
- }
- }
- }
- return schedule;
- }
- function prepareExpr(expr) {
- var prepared = expr.toUpperCase();
- return REPLACEMENTS[prepared] || prepared;
- }
- var e = prepareExpr(expr);
- return parseExpr(hasSeconds ? e : "0 " + e);
- };
- later.parse.recur = function() {
- var schedules = [], exceptions = [], cur, curArr = schedules, curName, values, every, modifier, applyMin, applyMax, i, last;
- function add(name, min, max) {
- name = modifier ? name + "_" + modifier : name;
- if (!cur) {
- curArr.push({});
- cur = curArr[0];
- }
- if (!cur[name]) {
- cur[name] = [];
- }
- curName = cur[name];
- if (every) {
- values = [];
- for (i = min; i <= max; i += every) {
- values.push(i);
- }
- last = {
- n: name,
- x: every,
- c: curName.length,
- m: max
- };
- }
- values = applyMin ? [ min ] : applyMax ? [ max ] : values;
- var length = values.length;
- for (i = 0; i < length; i += 1) {
- var val = values[i];
- if (curName.indexOf(val) < 0) {
- curName.push(val);
- }
- }
- values = every = modifier = applyMin = applyMax = 0;
- }
- return {
- schedules: schedules,
- exceptions: exceptions,
- on: function() {
- values = arguments[0] instanceof Array ? arguments[0] : arguments;
- return this;
- },
- every: function(x) {
- every = x || 1;
- return this;
- },
- after: function(x) {
- modifier = "a";
- values = [ x ];
- return this;
- },
- before: function(x) {
- modifier = "b";
- values = [ x ];
- return this;
- },
- first: function() {
- applyMin = 1;
- return this;
- },
- last: function() {
- applyMax = 1;
- return this;
- },
- time: function() {
- for (var i = 0, len = values.length; i < len; i++) {
- var split = values[i].split(":");
- if (split.length < 3) split.push(0);
- values[i] = +split[0] * 3600 + +split[1] * 60 + +split[2];
- }
- add("t");
- return this;
- },
- second: function() {
- add("s", 0, 59);
- return this;
- },
- minute: function() {
- add("m", 0, 59);
- return this;
- },
- hour: function() {
- add("h", 0, 23);
- return this;
- },
- dayOfMonth: function() {
- add("D", 1, applyMax ? 0 : 31);
- return this;
- },
- dayOfWeek: function() {
- add("d", 1, 7);
- return this;
- },
- onWeekend: function() {
- values = [ 1, 7 ];
- return this.dayOfWeek();
- },
- onWeekday: function() {
- values = [ 2, 3, 4, 5, 6 ];
- return this.dayOfWeek();
- },
- dayOfWeekCount: function() {
- add("dc", 1, applyMax ? 0 : 5);
- return this;
- },
- dayOfYear: function() {
- add("dy", 1, applyMax ? 0 : 366);
- return this;
- },
- weekOfMonth: function() {
- add("wm", 1, applyMax ? 0 : 5);
- return this;
- },
- weekOfYear: function() {
- add("wy", 1, applyMax ? 0 : 53);
- return this;
- },
- month: function() {
- add("M", 1, 12);
- return this;
- },
- year: function() {
- add("Y", 1970, 2450);
- return this;
- },
- fullDate: function() {
- for (var i = 0, len = values.length; i < len; i++) {
- values[i] = values[i].getTime();
- }
- add("fd");
- return this;
- },
- customModifier: function(id, vals) {
- var custom = later.modifier[id];
- if (!custom) throw new Error("Custom modifier " + id + " not recognized!");
- modifier = id;
- values = arguments[1] instanceof Array ? arguments[1] : [ arguments[1] ];
- return this;
- },
- customPeriod: function(id) {
- var custom = later[id];
- if (!custom) throw new Error("Custom time period " + id + " not recognized!");
- add(id, custom.extent(new Date())[0], custom.extent(new Date())[1]);
- return this;
- },
- startingOn: function(start) {
- return this.between(start, last.m);
- },
- between: function(start, end) {
- cur[last.n] = cur[last.n].splice(0, last.c);
- every = last.x;
- add(last.n, start, end);
- return this;
- },
- and: function() {
- cur = curArr[curArr.push({}) - 1];
- return this;
- },
- except: function() {
- curArr = exceptions;
- cur = null;
- return this;
- }
- };
- };
- later.parse.text = function(str) {
- var recur = later.parse.recur, pos = 0, input = "", error;
- var TOKENTYPES = {
- eof: /^$/,
- rank: /^((\d\d\d\d)|([2-5]?1(st)?|[2-5]?2(nd)?|[2-5]?3(rd)?|(0|[1-5]?[4-9]|[1-5]0|1[1-3])(th)?))\b/,
- time: /^((([0]?[1-9]|1[0-2]):[0-5]\d(\s)?(am|pm))|(([0]?\d|1\d|2[0-3]):[0-5]\d))\b/,
- dayName: /^((sun|mon|tue(s)?|wed(nes)?|thu(r(s)?)?|fri|sat(ur)?)(day)?)\b/,
- monthName: /^(jan(uary)?|feb(ruary)?|ma((r(ch)?)?|y)|apr(il)?|ju(ly|ne)|aug(ust)?|oct(ober)?|(sept|nov|dec)(ember)?)\b/,
- yearIndex: /^(\d\d\d\d)\b/,
- every: /^every\b/,
- after: /^after\b/,
- before: /^before\b/,
- second: /^(s|sec(ond)?(s)?)\b/,
- minute: /^(m|min(ute)?(s)?)\b/,
- hour: /^(h|hour(s)?)\b/,
- day: /^(day(s)?( of the month)?)\b/,
- dayInstance: /^day instance\b/,
- dayOfWeek: /^day(s)? of the week\b/,
- dayOfYear: /^day(s)? of the year\b/,
- weekOfYear: /^week(s)?( of the year)?\b/,
- weekOfMonth: /^week(s)? of the month\b/,
- weekday: /^weekday\b/,
- weekend: /^weekend\b/,
- month: /^month(s)?\b/,
- year: /^year(s)?\b/,
- between: /^between (the)?\b/,
- start: /^(start(ing)? (at|on( the)?)?)\b/,
- at: /^(at|@)\b/,
- and: /^(,|and\b)/,
- except: /^(except\b)/,
- also: /(also)\b/,
- first: /^(first)\b/,
- last: /^last\b/,
- "in": /^in\b/,
- of: /^of\b/,
- onthe: /^on the\b/,
- on: /^on\b/,
- through: /(-|^(to|through)\b)/
- };
- var NAMES = {
- jan: 1,
- feb: 2,
- mar: 3,
- apr: 4,
- may: 5,
- jun: 6,
- jul: 7,
- aug: 8,
- sep: 9,
- oct: 10,
- nov: 11,
- dec: 12,
- sun: 1,
- mon: 2,
- tue: 3,
- wed: 4,
- thu: 5,
- fri: 6,
- sat: 7,
- "1st": 1,
- fir: 1,
- "2nd": 2,
- sec: 2,
- "3rd": 3,
- thi: 3,
- "4th": 4,
- "for": 4
- };
- function t(start, end, text, type) {
- return {
- startPos: start,
- endPos: end,
- text: text,
- type: type
- };
- }
- function peek(expected) {
- var scanTokens = expected instanceof Array ? expected : [ expected ], whiteSpace = /\s+/, token, curInput, m, scanToken, start, len;
- scanTokens.push(whiteSpace);
- start = pos;
- while (!token || token.type === whiteSpace) {
- len = -1;
- curInput = input.substring(start);
- token = t(start, start, input.split(whiteSpace)[0]);
- var i, length = scanTokens.length;
- for (i = 0; i < length; i++) {
- scanToken = scanTokens[i];
- m = scanToken.exec(curInput);
- if (m && m.index === 0 && m[0].length > len) {
- len = m[0].length;
- token = t(start, start + len, curInput.substring(0, len), scanToken);
- }
- }
- if (token.type === whiteSpace) {
- start = token.endPos;
- }
- }
- return token;
- }
- function scan(expectedToken) {
- var token = peek(expectedToken);
- pos = token.endPos;
- return token;
- }
- function parseThroughExpr(tokenType) {
- var start = +parseTokenValue(tokenType), end = checkAndParse(TOKENTYPES.through) ? +parseTokenValue(tokenType) : start, nums = [];
- for (var i = start; i <= end; i++) {
- nums.push(i);
- }
- return nums;
- }
- function parseRanges(tokenType) {
- var nums = parseThroughExpr(tokenType);
- while (checkAndParse(TOKENTYPES.and)) {
- nums = nums.concat(parseThroughExpr(tokenType));
- }
- return nums;
- }
- function parseEvery(r) {
- var num, period, start, end;
- if (checkAndParse(TOKENTYPES.weekend)) {
- r.on(NAMES.sun, NAMES.sat).dayOfWeek();
- } else if (checkAndParse(TOKENTYPES.weekday)) {
- r.on(NAMES.mon, NAMES.tue, NAMES.wed, NAMES.thu, NAMES.fri).dayOfWeek();
- } else {
- num = parseTokenValue(TOKENTYPES.rank);
- r.every(num);
- period = parseTimePeriod(r);
- if (checkAndParse(TOKENTYPES.start)) {
- num = parseTokenValue(TOKENTYPES.rank);
- r.startingOn(num);
- parseToken(period.type);
- } else if (checkAndParse(TOKENTYPES.between)) {
- start = parseTokenValue(TOKENTYPES.rank);
- if (checkAndParse(TOKENTYPES.and)) {
- end = parseTokenValue(TOKENTYPES.rank);
- r.between(start, end);
- }
- }
- }
- }
- function parseOnThe(r) {
- if (checkAndParse(TOKENTYPES.first)) {
- r.first();
- } else if (checkAndParse(TOKENTYPES.last)) {
- r.last();
- } else {
- r.on(parseRanges(TOKENTYPES.rank));
- }
- parseTimePeriod(r);
- }
- function parseScheduleExpr(str) {
- pos = 0;
- input = str;
- error = -1;
- var r = recur();
- while (pos < input.length && error < 0) {
- var token = parseToken([ TOKENTYPES.every, TOKENTYPES.after, TOKENTYPES.before, TOKENTYPES.onthe, TOKENTYPES.on, TOKENTYPES.of, TOKENTYPES["in"], TOKENTYPES.at, TOKENTYPES.and, TOKENTYPES.except, TOKENTYPES.also ]);
- switch (token.type) {
- case TOKENTYPES.every:
- parseEvery(r);
- break;
- case TOKENTYPES.after:
- if (peek(TOKENTYPES.time).type !== undefined) {
- r.after(parseTokenValue(TOKENTYPES.time));
- r.time();
- } else {
- r.after(parseTokenValue(TOKENTYPES.rank));
- parseTimePeriod(r);
- }
- break;
- case TOKENTYPES.before:
- if (peek(TOKENTYPES.time).type !== undefined) {
- r.before(parseTokenValue(TOKENTYPES.time));
- r.time();
- } else {
- r.before(parseTokenValue(TOKENTYPES.rank));
- parseTimePeriod(r);
- }
- break;
- case TOKENTYPES.onthe:
- parseOnThe(r);
- break;
- case TOKENTYPES.on:
- r.on(parseRanges(TOKENTYPES.dayName)).dayOfWeek();
- break;
- case TOKENTYPES.of:
- r.on(parseRanges(TOKENTYPES.monthName)).month();
- break;
- case TOKENTYPES["in"]:
- r.on(parseRanges(TOKENTYPES.yearIndex)).year();
- break;
- case TOKENTYPES.at:
- r.on(parseTokenValue(TOKENTYPES.time)).time();
- while (checkAndParse(TOKENTYPES.and)) {
- r.on(parseTokenValue(TOKENTYPES.time)).time();
- }
- break;
- case TOKENTYPES.and:
- break;
- case TOKENTYPES.also:
- r.and();
- break;
- case TOKENTYPES.except:
- r.except();
- break;
- default:
- error = pos;
- }
- }
- return {
- schedules: r.schedules,
- exceptions: r.exceptions,
- error: error
- };
- }
- function parseTimePeriod(r) {
- var timePeriod = parseToken([ TOKENTYPES.second, TOKENTYPES.minute, TOKENTYPES.hour, TOKENTYPES.dayOfYear, TOKENTYPES.dayOfWeek, TOKENTYPES.dayInstance, TOKENTYPES.day, TOKENTYPES.month, TOKENTYPES.year, TOKENTYPES.weekOfMonth, TOKENTYPES.weekOfYear ]);
- switch (timePeriod.type) {
- case TOKENTYPES.second:
- r.second();
- break;
- case TOKENTYPES.minute:
- r.minute();
- break;
- case TOKENTYPES.hour:
- r.hour();
- break;
- case TOKENTYPES.dayOfYear:
- r.dayOfYear();
- break;
- case TOKENTYPES.dayOfWeek:
- r.dayOfWeek();
- break;
- case TOKENTYPES.dayInstance:
- r.dayOfWeekCo