-
-
Save jsmayo/0d988f002ad89e373c4530ee3d445638 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******/ (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 = 0); | |
/******/ }) | |
/************************************************************************/ | |
/******/ ([ | |
/* 0 */ | |
/***/ (function(module, exports) { | |
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.dayOfWeekCount(); | |
break; | |
case TOKENTYPES.day: | |
r.dayOfMonth(); | |
break; | |
case TOKENTYPES.weekOfMonth: | |
r.weekOfMonth(); | |
break; | |
case TOKENTYPES.weekOfYear: | |
r.weekOfYear(); | |
break; | |
case TOKENTYPES.month: | |
r.month(); | |
break; | |
case TOKENTYPES.year: | |
r.year(); | |
break; | |
default: | |
error = pos; | |
} | |
return timePeriod; | |
} | |
function checkAndParse(tokenType) { | |
var found = peek(tokenType).type === tokenType; | |
if (found) { | |
scan(tokenType); | |
} | |
return found; | |
} | |
function parseToken(tokenType) { | |
var t = scan(tokenType); | |
if (t.type) { | |
t.text = convertString(t.text, tokenType); | |
} else { | |
error = pos; | |
} | |
return t; | |
} | |
function parseTokenValue(tokenType) { | |
return parseToken(tokenType).text; | |
} | |
function convertString(str, tokenType) { | |
var output = str; | |
switch (tokenType) { | |
case TOKENTYPES.time: | |
var parts = str.split(/(:|am|pm)/), hour = parts[3] === "pm" && parts[0] < 12 ? parseInt(parts[0], 10) + 12 : parts[0], min = parts[2].trim(); | |
output = (hour.length === 1 ? "0" : "") + hour + ":" + min; | |
break; | |
case TOKENTYPES.rank: | |
output = parseInt(/^\d+/.exec(str)[0], 10); | |
break; | |
case TOKENTYPES.monthName: | |
case TOKENTYPES.dayName: | |
output = NAMES[str.substring(0, 3)]; | |
break; | |
} | |
return output; | |
} | |
return parseScheduleExpr(str.toLowerCase()); | |
}; | |
return later; | |
}(); | |
/***/ }) | |
/******/ ]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment