UNPKG

half-past

Version:

natural-language date-parsing in javascript

2,115 lines (1,712 loc) 146 kB
/* half-past v0.0.3 github.com/spencermountain/half-past MIT */ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.halfPast = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){ (function (global){ /* spacetime v5.1.0 github.com/spencermountain/spacetime MIT */ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.spacetime = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof _dereq_&&_dereq_;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof _dereq_&&_dereq_,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){ "use strict"; module.exports = '5.1.0'; },{}],2:[function(_dereq_,module,exports){ 'use strict'; var shortDays = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; var longDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']; module.exports = { short: function short() { return shortDays; }, long: function long() { return longDays; }, set: function set(i18n) { shortDays = i18n.short; longDays = i18n.long; } }; },{}],3:[function(_dereq_,module,exports){ 'use strict'; var o = { millisecond: 1 }; o.second = 1000; o.minute = 60000; o.hour = 3.6e6; // dst is supported post-hoc o.day = 8.64e7; // o.date = o.day; o.month = 8.64e7 * 29.5; //(average) o.week = 6.048e8; o.year = 3.154e10; // leap-years are supported post-hoc //add plurals Object.keys(o).forEach(function (k) { o[k + 's'] = o[k]; }); module.exports = o; },{}],4:[function(_dereq_,module,exports){ "use strict"; var monthLengths = [31, // January - 31 days 28, // February - 28 days in a common year and 29 days in leap years 31, // March - 31 days 30, // April - 30 days 31, // May - 31 days 30, // June - 30 days 31, // July - 31 days 31, // August - 31 days 30, // September - 30 days 31, // October - 31 days 30, // November - 30 days 31 // December - 31 days ]; module.exports = monthLengths; },{}],5:[function(_dereq_,module,exports){ 'use strict'; var shortMonths = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sept', 'oct', 'nov', 'dec']; var longMonths = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; function buildMapping() { var obj = { sep: 8 //support this format }; for (var i = 0; i < shortMonths.length; i++) { obj[shortMonths[i]] = i; } for (var _i = 0; _i < longMonths.length; _i++) { obj[longMonths[_i]] = _i; } return obj; } module.exports = { short: function short() { return shortMonths; }, long: function long() { return longMonths; }, mapping: function mapping() { return buildMapping(); }, set: function set(i18n) { shortMonths = i18n.short; longMonths = i18n.long; } }; },{}],6:[function(_dereq_,module,exports){ "use strict"; module.exports = [null, [0, 1], //jan 1 [3, 1], //apr 1 [6, 1], //july 1 [9, 1]]; },{}],7:[function(_dereq_,module,exports){ "use strict"; //https://www.timeanddate.com/calendar/aboutseasons.html // Spring - from March 1 to May 31; // Summer - from June 1 to August 31; // Fall (autumn) - from September 1 to November 30; and, // Winter - from December 1 to February 28 (February 29 in a leap year). module.exports = { north: [['spring', 2, 1], //spring march 1 ['summer', 5, 1], //june 1 ['fall', 8, 1], //sept 1 ['autumn', 8, 1], //sept 1 ['winter', 11, 1] //dec 1 ], south: [['fall', 2, 1], //march 1 ['autumn', 2, 1], //march 1 ['winter', 5, 1], //june 1 ['spring', 8, 1], //sept 1 ['summer', 11, 1] //dec 1 ] }; },{}],8:[function(_dereq_,module,exports){ 'use strict'; //git:blame @JuliasCaesar https://www.timeanddate.com/date/leapyear.html exports.isLeapYear = function (year) { return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; }; // unsurprisingly-nasty `typeof date` call exports.isDate = function (d) { return Object.prototype.toString.call(d) === '[object Date]' && !isNaN(d.valueOf()); }; exports.isArray = function (input) { return Object.prototype.toString.call(input) === '[object Array]'; }; exports.isObject = function (input) { return Object.prototype.toString.call(input) === '[object Object]'; }; exports.zeroPad = function (str, len) { len = len || 2; var pad = '0'; str = str + ''; return str.length >= len ? str : new Array(len - str.length + 1).join(pad) + str; }; exports.titleCase = function (str) { if (!str) { return ''; } return str[0].toUpperCase() + str.substr(1); }; exports.ordinal = function (i) { var j = i % 10; var k = i % 100; if (j === 1 && k !== 11) { return i + 'st'; } if (j === 2 && k !== 12) { return i + 'nd'; } if (j === 3 && k !== 13) { return i + 'rd'; } return i + 'th'; }; //strip 'st' off '1st'.. exports.toCardinal = function (str) { str = String(str); str = str.replace(/([0-9])(st|nd|rd|th)$/i, '$1'); return parseInt(str, 10); }; exports.normalize = function (str) { str = str.toLowerCase(); str = str.replace(/s$/, ''); if (str === 'day') { return 'date'; } return str; }; exports.getEpoch = function (tmp) { //support epoch if (typeof tmp === 'number') { return tmp; } //suport date objects if (exports.isDate(tmp)) { return tmp.getTime(); } if (tmp.epoch) { return tmp.epoch; } return null; }; //make sure this input is a spacetime obj exports.beADate = function (d, s) { if (exports.isObject(d) === false) { return s.clone().set(d); } return d; }; },{}],9:[function(_dereq_,module,exports){ 'use strict'; var Spacetime = _dereq_('./spacetime'); var whereIts = _dereq_('./whereIts'); var version = _dereq_('../_version'); var main = function main(input, tz, options) { return new Spacetime(input, tz, options); }; //some helper functions on the main method main.now = function (tz, options) { return new Spacetime(new Date().getTime(), tz, options); }; main.today = function (tz, options) { var s = new Spacetime(new Date().getTime(), tz, options); return s.startOf('day'); }; main.tomorrow = function (tz, options) { var s = new Spacetime(new Date().getTime(), tz, options); return s.add(1, 'day').startOf('day'); }; main.yesterday = function (tz, options) { var s = new Spacetime(new Date().getTime(), tz, options); return s.subtract(1, 'day').startOf('day'); }; main.extend = function (obj) { Object.keys(obj).forEach(function (k) { Spacetime.prototype[k] = obj[k]; }); return this; }; //find tz by time main.whereIts = whereIts; main.version = version; //aliases: main.plugin = main.extend; module.exports = main; },{"../_version":1,"./spacetime":34,"./whereIts":41}],10:[function(_dereq_,module,exports){ 'use strict'; var monthLengths = _dereq_('../data/monthLengths'); var isLeapYear = _dereq_('../fns').isLeapYear; //given a month, return whether day number exists in it var hasDate = function hasDate(obj) { //invalid values if (monthLengths.hasOwnProperty(obj.month) !== true) { return false; } //support leap-year in february if (obj.month === 1) { if (isLeapYear(obj.year) && obj.date <= 29) { return true; } else { return obj.date <= 28; } } //is this date too-big for this month? var max = monthLengths[obj.month] || 0; if (obj.date <= max) { return true; } return false; }; module.exports = hasDate; },{"../data/monthLengths":4,"../fns":8}],11:[function(_dereq_,module,exports){ 'use strict'; var strFmt = _dereq_('./strParse'); var fns = _dereq_('../fns'); var namedDates = _dereq_('./named-dates'); //we have to actually parse these inputs ourselves // - can't use built-in js parser ;( //========================================= // ISO Date "2015-03-25" // Short Date "03/25/2015" or "2015/03/25" // Long Date "Mar 25 2015" or "25 Mar 2015" // Full Date "Wednesday March 25 2015" //========================================= //-- also - // if the given epoch is really small, they've probably given seconds and not milliseconds // anything below this number is likely (but not necessarily) a mistaken input. // this may seem like an arbitrary number, but it's 'within jan 1970' // this is only really ambiguous until 2054 or so var minimumEpoch = 2500000000; //support [2016, 03, 01] format var handleArray = function handleArray(s, arr) { var order = ['year', 'month', 'date', 'hour', 'minute', 'second', 'millisecond']; for (var i = 0; i < arr.length; i++) { var num = arr[i] || 0; s = s[order[i]](num); } return s; }; //support {year:2016, month:3} format var handleObject = function handleObject(s, obj) { var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { var unit = keys[i]; if (s[unit] !== undefined) { var num = obj[unit] || 0; s = s[unit](num); } } return s; }; //find the epoch from different input styles var parseInput = function parseInput(s, input, givenTz) { //if we've been given a epoch number, it's easy if (typeof input === 'number') { if (input > 0 && input < minimumEpoch && s.silent === false) { console.warn(' - Warning: You are setting the date to January 1970.'); console.warn(' - did input seconds instead of milliseconds?'); } s.epoch = input; return s; } //set tmp time s.epoch = Date.now(); if (input === null || input === undefined) { return s; //k, we're good. } //support input of Date() object if (fns.isDate(input) === true) { s.epoch = input.getTime(); return s; } //support [2016, 03, 01] format if (fns.isArray(input) === true) { s = handleArray(s, input); return s; } //support {year:2016, month:3} format if (fns.isObject(input) === true) { //support spacetime object as input if (input.epoch) { s.epoch = input.epoch; return s; } s = handleObject(s, input); return s; } //input as a string.. if (typeof input !== 'string') { return s; } //little cleanup.. input = input.replace(/\b(mon|tues|wed|wednes|thu|thurs|fri|sat|satur|sun)(day)?\b/, ''); input = input.trim().replace(/ +/g, ' '); //try some known-words, like 'now' if (namedDates.hasOwnProperty(input) === true) { s = namedDates[input](s); return s; } //try each text-parse template, use the first good result for (var i = 0; i < strFmt.length; i++) { var m = input.match(strFmt[i].reg); if (m) { s = strFmt[i].parse(s, m, givenTz); return s; } } if (s.silent === false) { console.warn('Warning: couldn\'t parse date-string: \'' + input + '\''); } s.epoch = null; return s; }; module.exports = parseInput; },{"../fns":8,"./named-dates":12,"./strParse":14}],12:[function(_dereq_,module,exports){ 'use strict'; var dates = { now: function now(s) { s.epoch = Date.now(); return s; }, tonight: function tonight(s) { s.epoch = Date.now(); s = s.hour(18); return s; }, today: function today(s) { s.epoch = Date.now(); return s; }, tomorrow: function tomorrow(s) { s.epoch = Date.now(); s = s.add(1, 'day'); s = s.startOf('day'); return s; }, yesterday: function yesterday(s) { s.epoch = Date.now(); s = s.subtract(1, 'day'); s = s.startOf('day'); return s; }, christmas: function christmas(s) { var year = new Date().getFullYear(); s = s.set([year, 11, 25, 18, 0, 0]); // Dec 25 return s; }, 'new years': function newYears(s) { var year = new Date().getFullYear(); s = s.set([year, 11, 31, 18, 0, 0]); // Dec 31 return s; } }; dates['new years eve'] = dates['new years']; module.exports = dates; },{}],13:[function(_dereq_,module,exports){ 'use strict'; //pull-apart ISO offsets, like "+0100" var parseOffset = function parseOffset(s, offset) { if (!offset) { return s; } //this is a fancy-move if (offset === 'Z') { offset = '+0000'; } //support "+01:00" if (/:00/.test(offset) === true) { offset = offset.replace(/:00/, ''); } //support "+01:30" if (/:00/.test(offset) === true) { offset = offset.replace(/:00/, '.5'); } var num = parseInt(offset, 10); //divide by 100 or 10 - , "+0100", "+01" if (Math.abs(num) > 100) { num = num / 100; } // console.log(offset, num) var current = s.timezone().current.offset; if (current === num) { //we cool.. return s; } //okay, try to match it to a utc timezone //this is opposite! a -5 offset maps to Etc/GMT+5 ¯\_()_/¯ //https://askubuntu.com/questions/519550/why-is-the-8-timezone-called-gmt-8-in-the-filesystem num *= -1; if (num >= 0) { num = '+' + num; } var tz = 'etc/gmt' + num; var zones = s.timezones; // console.log(tz) if (zones[tz]) { // console.log('changing timezone to: ' + tz) //log a warning if we're over-writing a given timezone // if (givenTz && zones[givenTz] && zones[givenTz].offset !== zones[tz].offset && s.silent === false) { //don't log during our tests, either.. // if (typeof process !== 'undefined' && process.env && !process.env.TESTENV) { // console.warn(' - Setting timezone to: \'' + tz + '\'') // console.warn(' from ISO string \'' + offset + '\'') // console.warn(' overwriting given timezone: \'' + givenTz + '\'\n') // } // } s.tz = tz; } return s; }; module.exports = parseOffset; },{}],14:[function(_dereq_,module,exports){ 'use strict'; var walkTo = _dereq_('../methods/set/walk'); var months = _dereq_('../data/months').mapping(); var parseOffset = _dereq_('./parseOffset'); var hasDate = _dereq_('./hasDate'); var fns = _dereq_('../fns'); // const zones = require('../../data'); var parseHour = function parseHour(s, str) { str = str.replace(/^\s+/, ''); //trim var arr = str.match(/([0-9]{1,2}):([0-9]{1,2}):?([0-9]{1,2})?[:\.]?([0-9]{1,4})?/); if (arr) { s = s.hour(arr[1]); s = s.minute(arr[2]); if (arr[3]) { s = s.seconds(arr[3]); } if (arr[4]) { s = s.millisecond(arr[4]); } } return s; }; var parseYear = function parseYear(str) { str = str || ''; //support '18 -> 2018 // str = str.replace(/^'([0-9]{2})/, '20$1') // str = str.replace('([0-9]+) ?b\.?c\.?$', '-$1') var year = parseInt(str.trim(), 10); year = year || new Date().getFullYear(); return year; }; var strFmt = [//iso-this 1998-05-30T22:00:00:000Z, iso-that 2017-04-03T08:00:00-0700 { reg: /^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})[T| ]([0-9.:]+)(Z|[0-9\-\+:]+)?$/, parse: function parse(s, arr, givenTz, options) { var month = parseInt(arr[2], 10) - 1; var obj = { year: arr[1], month: month, date: arr[3] }; if (hasDate(obj) === false) { s.epoch = null; return s; } parseOffset(s, arr[5], givenTz, options); walkTo(s, obj); s = parseHour(s, arr[4]); return s; } }, //iso "2015-03-25" or "2015/03/25" //0-based-months! { reg: /^([0-9]{4})[\-\/]([0-9]{1,2})[\-\/]([0-9]{1,2})$/, parse: function parse(s, arr) { var obj = { year: arr[1], month: parseInt(arr[2], 10) - 1, date: parseInt(arr[3], 10) }; if (obj.month >= 12) { //support yyyy/dd/mm (weird, but ok) obj.date = parseInt(arr[2], 10); obj.month = parseInt(arr[3], 10) - 1; } if (hasDate(obj) === false) { s.epoch = null; return s; } walkTo(s, obj); return s; } }, //short - uk "03/25/2015" //0-based-months! { reg: /^([0-9]{1,2})[\-\/]([0-9]{1,2})[\-\/]?([0-9]{4})?$/, parse: function parse(s, arr) { var month = parseInt(arr[1], 10) - 1; var date = parseInt(arr[2], 10); if (month >= 12) { //support yyyy/dd/mm (weird, but ok) month = parseInt(arr[2], 10) - 1; date = parseInt(arr[1], 10); } var year = arr[3] || new Date().getFullYear(); var obj = { year: year, month: month, date: date }; if (hasDate(obj) === false) { s.epoch = null; return s; } walkTo(s, obj); return s; } }, //Long "Mar 25 2015" //February 22, 2017 15:30:00 { reg: /^([a-z]+) ([0-9]{1,2}(?:st|nd|rd|th)?),?( [0-9]{4})?( ([0-9:]+))?$/i, parse: function parse(s, arr) { var month = months[arr[1].toLowerCase()]; var year = parseYear(arr[3]); var obj = { year: year, month: month, date: fns.toCardinal(arr[2] || '') }; if (hasDate(obj) === false) { s.epoch = null; return s; } walkTo(s, obj); if (arr[4]) { s = parseHour(s, arr[4]); } return s; } }, //February 2017 (implied date) { reg: /^([a-z]+) ([0-9]{4})$/i, parse: function parse(s, arr) { var month = months[arr[1].toLowerCase()]; var year = parseYear(arr[2]); var obj = { year: year, month: month, date: 1 }; if (hasDate(obj) === false) { s.epoch = null; return s; } walkTo(s, obj); if (arr[4]) { s = parseHour(s, arr[4]); } return s; } }, //Long "25 Mar 2015" { reg: /^([0-9]{1,2}(?:st|nd|rd|th)?) ([a-z]+),?( [0-9]{4})?$/i, parse: function parse(s, arr) { var month = months[arr[2].toLowerCase()]; var year = parseYear(arr[3]); var obj = { year: year, month: month, date: fns.toCardinal(arr[1]) }; if (hasDate(obj) === false) { s.epoch = null; return s; } walkTo(s, obj); return s; } }, { // '1992' reg: /^[0-9]{4}$/i, parse: function parse(s, arr) { var year = parseYear(arr[0]); var d = new Date(); var obj = { year: year, month: d.getMonth(), date: d.getDate() }; if (hasDate(obj) === false) { s.epoch = null; return s; } walkTo(s, obj); return s; } }, { // '200bc' reg: /^[0-9,]+ ?b\.?c\.?$/i, parse: function parse(s, arr) { var str = arr[0] || ''; //make negative-year str = str.replace(/^([0-9,]+) ?b\.?c\.?$/i, '-$1'); //remove commas str = str.replace(/,/g, ''); var year = parseInt(str.trim(), 10); var d = new Date(); var obj = { year: year, month: d.getMonth(), date: d.getDate() }; if (hasDate(obj) === false) { s.epoch = null; return s; } walkTo(s, obj); return s; } }]; module.exports = strFmt; },{"../data/months":5,"../fns":8,"../methods/set/walk":31,"./hasDate":10,"./parseOffset":13}],15:[function(_dereq_,module,exports){ 'use strict'; var _format = _dereq_('./methods/format'); var _unixFmt = _dereq_('./methods/format/unixFmt'); var _progress = _dereq_('./methods/progress'); var _nearest = _dereq_('./methods/nearest'); var _diff = _dereq_('./methods/diff'); var _since = _dereq_('./methods/since'); var ends = _dereq_('./methods/startOf'); var _timezone = _dereq_('./timezone/index'); var findTz = _dereq_('./timezone/find'); var handleInput = _dereq_('./input'); var fns = _dereq_('./fns'); //the spacetime instance methods (also, the API) var methods = { set: function set(input) { var s = this.clone(); s = handleInput(s, input); return s; }, timezone: function timezone() { return _timezone(this); }, isDST: function isDST() { return _timezone(this).current.isDST; }, hasDST: function hasDST() { return _timezone(this).hasDst; }, offset: function offset() { return _timezone(this).current.offset * 60; }, hemisphere: function hemisphere() { return _timezone(this).hemisphere; }, format: function format(fmt) { return _format(this, fmt); }, unixFmt: function unixFmt(fmt) { return _unixFmt(this, fmt); }, startOf: function startOf(unit) { return ends.startOf(this, unit); }, endOf: function endOf(unit) { return ends.endOf(this, unit); }, leapYear: function leapYear() { var year = this.year(); return fns.isLeapYear(year); }, progress: function progress() { return _progress(this); }, nearest: function nearest(unit) { return _nearest(this, unit); }, diff: function diff(d, unit) { return _diff(this, d, unit); }, since: function since(d) { if (!d) { d = this.clone().set(); } return _since(this, d); }, isValid: function isValid() { //null/undefined epochs if (!this.epoch && this.epoch !== 0) { return false; } return !isNaN(this.d.getTime()); }, //travel to this timezone goto: function goto(tz) { var s = this.clone(); s.tz = findTz(tz, s.timezones); //science! return s; }, isAwake: function isAwake() { var hour = this.hour(); //10pm -> 8am if (hour < 8 || hour > 22) { return false; } return true; }, isAsleep: function isAsleep() { return !this.isAwake(); }, //pretty-printing log: function log() { console.log(''); console.log(_format(this, 'nice-short')); return this; }, logYear: function logYear() { console.log(''); console.log(_format(this, 'full-short')); return this; }, debug: function debug() { var tz = this.timezone(); var date = this.format('MM') + ' ' + this.format('date-ordinal') + ' ' + this.year(); date += '\n - ' + this.format('time'); console.log('\n\n', date + '\n - ' + tz.name + ' (' + tz.current.offset + ')'); return this; } // aliases }; methods.inDST = methods.isDST; methods.round = methods.nearest; module.exports = methods; },{"./fns":8,"./input":11,"./methods/diff":18,"./methods/format":20,"./methods/format/unixFmt":21,"./methods/nearest":23,"./methods/progress":24,"./methods/since":32,"./methods/startOf":33,"./timezone/find":36,"./timezone/index":38}],16:[function(_dereq_,module,exports){ 'use strict'; var walkTo = _dereq_('./set/walk'); var ms = _dereq_('../data/milliseconds'); var monthLength = _dereq_('../data/monthLengths'); var fns = _dereq_('../fns'); var order = ['millisecond', 'second', 'minute', 'hour', 'date', 'month']; var keep = { second: order.slice(0, 1), minute: order.slice(0, 2), quarterhour: order.slice(0, 2), hour: order.slice(0, 3), date: order.slice(0, 4), month: order.slice(0, 4), quarter: order.slice(0, 4), season: order.slice(0, 4), year: order }; keep.week = keep.date; keep.season = keep.date; keep.quarter = keep.date; var keepDate = { month: true, quarter: true, season: true, year: true }; //month is the only thing we 'model/compute' //- because ms-shifting can be off by enough var rollMonth = function rollMonth(want, old) { //increment year if (want.month > 0) { var years = parseInt(want.month / 12, 10); want.year = old.year() + years; want.month = want.month % 12; } else if (want.month < 0) { //decrement year var _years = Math.floor(Math.abs(want.month) / 13, 10); _years = Math.abs(_years) + 1; want.year = old.year() - _years; //ignore extras want.month = want.month % 12; want.month = want.month + 12; if (want.month === 12) { want.month = 0; } } return want; }; var addMethods = function addMethods(SpaceTime) { SpaceTime.prototype.add = function (num, unit) { var s = this.clone(); var old = this.clone(); unit = fns.normalize(unit); //move forward by the estimated milliseconds (rough) if (ms[unit]) { s.epoch += ms[unit] * num; } else if (unit === 'week') { s.epoch += ms.day * (num * 7); } else if (unit === 'quarter' || unit === 'season') { s.epoch += ms.month * (num * 4); } else if (unit === 'season') { s.epoch += ms.month * (num * 4); } else if (unit === 'quarterhour') { s.epoch += ms.minute * 15; } //now ensure our milliseconds/etc are in-line var want = {}; if (keep[unit]) { keep[unit].forEach(function (u) { want[u] = old[u](); }); } //ensure month/year has ticked-over if (unit === 'month') { want.month = old.month() + num; //month is the one unit we 'model' directly want = rollMonth(want, old); } //support 25-hour day-changes on dst-changes else if (unit === 'date' && num !== 0 && old.isSame(s, 'day')) { want.date = old.date() + num; } //ensure year has changed (leap-years) else if (unit === 'year' && s.year() === old.year()) { s.epoch += ms.week; } //keep current date, unless the month doesn't have it. if (keepDate[unit]) { var max = monthLength[want.month]; want.date = old.date(); if (want.date > max) { want.date = max; } } walkTo(s, want); return s; }; //subtract is only add *-1 SpaceTime.prototype.subtract = function (num, unit) { var s = this.clone(); return s.add(num * -1, unit); }; //add aliases SpaceTime.prototype.minus = SpaceTime.prototype.subtract; SpaceTime.prototype.plus = SpaceTime.prototype.add; }; module.exports = addMethods; },{"../data/milliseconds":3,"../data/monthLengths":4,"../fns":8,"./set/walk":31}],17:[function(_dereq_,module,exports){ 'use strict'; var fns = _dereq_('../fns'); var addMethods = function addMethods(SpaceTime) { var methods = { isAfter: function isAfter(d) { d = fns.beADate(d, this); var epoch = fns.getEpoch(d); if (epoch === null) { return null; } return this.epoch > epoch; }, isBefore: function isBefore(d) { d = fns.beADate(d, this); var epoch = fns.getEpoch(d); if (epoch === null) { return null; } return this.epoch < epoch; }, isEqual: function isEqual(d) { d = fns.beADate(d, this); var epoch = fns.getEpoch(d); if (epoch === null) { return null; } return this.epoch === epoch; }, isBetween: function isBetween(start, end) { start = fns.beADate(start, this); end = fns.beADate(end, this); var startEpoch = fns.getEpoch(start); if (startEpoch === null) { return null; } var endEpoch = fns.getEpoch(end); if (endEpoch === null) { return null; } return startEpoch < this.epoch && this.epoch < endEpoch; } }; //hook them into proto Object.keys(methods).forEach(function (k) { SpaceTime.prototype[k] = methods[k]; }); }; module.exports = addMethods; },{"../fns":8}],18:[function(_dereq_,module,exports){ 'use strict'; var fns = _dereq_('../fns'); //init this function up here var doAll = function doAll() {}; //increment until dates are the same var climb = function climb(a, b, unit) { var i = 0; a = a.clone(); while (a.isBefore(b)) { //do proper, expensive increment to catch all-the-tricks a = a.add(1, unit); i += 1; } //oops, we went too-far.. if (!a.isSame(b, unit)) { i -= 1; } return i; }; var diffQuick = function diffQuick(a, b) { var ms = b.epoch - a.epoch; var obj = { milliseconds: ms, seconds: parseInt(ms / 1000, 10) }; obj.minutes = parseInt(obj.seconds / 60, 10); obj.hours = parseInt(obj.minutes / 60, 10); return obj; }; var diff = function diff(a, b, unit) { //remove trailing s b = fns.beADate(b, a); if (!unit) { return doAll(a, b); } //make sure it's plural-form unit = fns.normalize(unit); if (/s$/.test(unit) !== true) { unit += 's'; } //do quick-form for these small-ones if (unit === 'milliseconds' || unit === 'seconds' || unit === 'minutes') { return diffQuick(a, b)[unit]; } //otherwise, do full-version if (a.isBefore(b)) { return climb(a, b, unit); } else { //reverse it return climb(b, a, unit) * -1; } }; doAll = function doAll(a, b) { //do ms, seconds, minutes in a faster way var all = diffQuick(a, b); all.years = diff(a, b, 'year'); all.months = diff(a, b, 'month'); all.weeks = diff(a, b, 'week'); all.days = diff(a, b, 'day'); //only slow-compute hours if it's a small diff if (all.years === 0) { all.hours = diff(a, b, 'hour'); } return all; }; module.exports = diff; },{"../fns":8}],19:[function(_dereq_,module,exports){ "use strict"; var fns = _dereq_('../../fns'); // "+01:00", "+0100", or simply "+01" var isoOffset = function isoOffset(s) { var offset = s.timezone().current.offset; var minute = '00'; if (offset % 1 === 0.5) { //fraction of the hour minute = '30'; offset = Math.floor(offset); } if (offset < 0) { //handle negative sign offset *= -1; offset = fns.zeroPad(offset, 2); offset = '-' + offset; } else { offset = fns.zeroPad(offset, 2); offset = '+' + offset; } offset = offset + ':' + minute; //this is a little cleaner? if (offset === "+00:00") { offset = 'Z'; } return offset; }; module.exports = isoOffset; },{"../../fns":8}],20:[function(_dereq_,module,exports){ 'use strict'; var fns = _dereq_('../../fns'); var months = _dereq_('../../data/months'); var days = _dereq_('../../data/days'); var isoOffset = _dereq_('./_offset'); var format = { day: function day(s) { return fns.titleCase(s.dayName()); }, 'day-short': function dayShort(s) { return fns.titleCase(days.short()[s.day()]); }, 'day-number': function dayNumber(s) { return s.day(); }, 'day-ordinal': function dayOrdinal(s) { return fns.ordinal(s.day()); }, 'day-pad': function dayPad(s) { return fns.zeroPad(s.day()); }, date: function date(s) { return s.date(); }, 'date-ordinal': function dateOrdinal(s) { return fns.ordinal(s.date()); }, 'date-pad': function datePad(s) { return fns.zeroPad(s.date()); }, month: function month(s) { return fns.titleCase(s.monthName()); }, 'month-short': function monthShort(s) { return fns.titleCase(months.short()[s.month()]); }, 'month-number': function monthNumber(s) { return s.month(); }, 'month-ordinal': function monthOrdinal(s) { return fns.ordinal(s.month()); }, 'month-pad': function monthPad(s) { return fns.zeroPad(s.month()); }, year: function year(s) { var year = s.year(); if (year > 0) { return year; } year = Math.abs(year); return year + ' BC'; }, 'year-short': function yearShort(s) { var year = s.year(); if (year > 0) { return "'".concat(String(s.year()).substr(2, 4)); } year = Math.abs(year); return year + ' BC'; }, time: function time(s) { return s.time(); }, 'time-24': function time24(s) { return "".concat(s.hour24(), ":").concat(fns.zeroPad(s.minute())); }, hour: function hour(s) { return s.hour12(); }, 'hour-24': function hour24(s) { return s.hour24(); }, minute: function minute(s) { return s.minute(); }, 'minute-pad': function minutePad(s) { return fns.zeroPad(s.minute()); }, second: function second(s) { return s.second(); }, 'second-pad': function secondPad(s) { return fns.zeroPad(s.second()); }, ampm: function ampm(s) { return s.ampm(); }, quarter: function quarter(s) { return 'Q' + s.quarter(); }, season: function season(s) { return s.season(); }, era: function era(s) { return s.era(); }, timezone: function timezone(s) { return s.timezone().name; }, offset: function offset(s) { return isoOffset(s); }, numeric: function numeric(s) { return "".concat(s.year(), "/").concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date())); }, // yyyy/mm/dd 'numeric-us': function numericUs(s) { return "".concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date()), "/").concat(s.year()); }, // mm/dd/yyyy 'numeric-uk': function numericUk(s) { return "".concat(fns.zeroPad(s.date()), "/").concat(fns.zeroPad(s.month() + 1), "/").concat(s.year()); }, //dd/mm/yyyy 'mm/dd': function mmDd(s) { return "".concat(fns.zeroPad(s.month() + 1), "/").concat(fns.zeroPad(s.date())); }, //mm/dd // ... https://en.wikipedia.org/wiki/ISO_8601 ;((( iso: function iso(s) { var month = fns.zeroPad(s.month() + 1); //1-based months var date = fns.zeroPad(s.date()); var hour = fns.zeroPad(s.h24()); var minute = fns.zeroPad(s.minute()); var second = fns.zeroPad(s.second()); var ms = fns.zeroPad(s.millisecond(), 3); var offset = isoOffset(s); return "".concat(s.year(), "-").concat(month, "-").concat(date, "T").concat(hour, ":").concat(minute, ":").concat(second, ".").concat(ms).concat(offset); //2018-03-09T08:50:00.000-05:00 }, 'iso-short': function isoShort(s) { var month = fns.zeroPad(s.month() + 1); //1-based months var date = fns.zeroPad(s.date()); return "".concat(s.year(), "-").concat(month, "-").concat(date); //2017-02-15 }, 'iso-utc': function isoUtc(s) { return new Date(s.epoch).toISOString(); //2017-03-08T19:45:28.367Z }, //i made these up 'nice': function nice(s) { return "".concat(months.short()[s.month()], " ").concat(fns.ordinal(s.date()), ", ").concat(s.time()); }, 'nice-year': function niceYear(s) { return "".concat(months.short()[s.month()], " ").concat(fns.ordinal(s.date()), ", ").concat(s.year()); }, 'nice-day': function niceDay(s) { return "".concat(days.short()[s.day()], " ").concat(fns.titleCase(months.short()[s.month()]), " ").concat(fns.ordinal(s.date())); }, 'nice-full': function niceFull(s) { return "".concat(s.dayName(), " ").concat(fns.titleCase(s.monthName()), " ").concat(fns.ordinal(s.date()), ", ").concat(s.time()); } //aliases }; var aliases = { 'day-name': 'day', 'month-name': 'month', 'iso 8601': 'iso', 'time-h24': 'time-24', 'time-12': 'time', 'time-h12': 'time', 'tz': 'timezone', 'day-num': 'day-number', 'month-num': 'month-number', 'nice-short': 'nice', 'mdy': 'numeric-us', 'dmy': 'numeric-uk', 'ymd': 'numeric', 'yyyy/mm/dd': 'numeric', 'mm/dd/yyyy': 'numeric-us', 'dd/mm/yyyy': 'numeric-us', 'little-endian': 'numeric-uk', 'big-endian': 'numeric' }; Object.keys(aliases).forEach(function (k) { return format[k] = format[aliases[k]]; }); var printFormat = function printFormat(s) { var str = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; //don't print anything if it's an invalid date if (s.isValid() !== true) { return ''; } //support .format('month') if (format.hasOwnProperty(str)) { var out = String(format[str](s) || ''); if (str !== 'ampm') { out = fns.titleCase(out); } return out; } //support '{hour}:{minute}' notation if (str.indexOf('{') !== -1) { var sections = /\{(.+?)\}/g; str = str.replace(sections, function (_, fmt) { fmt = fmt.toLowerCase().trim(); if (format.hasOwnProperty(fmt)) { return String(format[fmt](s) || ''); } return ''; }); return str; } return s.format('iso-short'); }; module.exports = printFormat; },{"../../data/days":2,"../../data/months":5,"../../fns":8,"./_offset":19}],21:[function(_dereq_,module,exports){ 'use strict'; var pad = _dereq_('../../fns').zeroPad; //parse this insane unix-time-templating thing, from the 19th century //http://unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns //time-symbols we support var mapping = { G: function G(s) { return s.era(); }, GG: function GG(s) { return s.era(); }, GGG: function GGG(s) { return s.era(); }, GGGG: function GGGG(s) { return s.era() === 'AD' ? 'Anno Domini' : 'Before Christ'; }, //year y: function y(s) { return s.year(); }, yy: function yy(s) { //last two chars return parseInt(String(s.year()).substr(2, 4), 10); }, yyy: function yyy(s) { return s.year(); }, yyyy: function yyyy(s) { return s.year(); }, yyyyy: function yyyyy(s) { return '0' + s.year(); }, // u: (s) => {},//extended non-gregorian years //quarter Q: function Q(s) { return s.quarter(); }, QQ: function QQ(s) { return s.quarter(); }, QQQ: function QQQ(s) { return s.quarter(); }, QQQQ: function QQQQ(s) { return s.quarter(); }, //month M: function M(s) { return s.month() + 1; }, MM: function MM(s) { return pad(s.month() + 1); }, MMM: function MMM(s) { return s.format('month-short'); }, MMMM: function MMMM(s) { return s.format('month'); }, //week w: function w(s) { return s.week(); }, ww: function ww(s) { return pad(s.week()); }, //week of month // W: (s) => s.week(), //date of month d: function d(s) { return s.date(); }, dd: function dd(s) { return pad(s.date()); }, //date of year D: function D(s) { return s.dayOfYear(); }, DD: function DD(s) { return pad(s.dayOfYear()); }, DDD: function DDD(s) { return pad(s.dayOfYear(), 3); }, // F: (s) => {},//date of week in month // g: (s) => {},//modified julian day //day E: function E(s) { return s.format('day-short'); }, EE: function EE(s) { return s.format('day-short'); }, EEE: function EEE(s) { return s.format('day-short'); }, EEEE: function EEEE(s) { return s.format('day'); }, EEEEE: function EEEEE(s) { return s.format('day')[0]; }, e: function e(s) { return s.day(); }, ee: function ee(s) { return s.day(); }, eee: function eee(s) { return s.format('day-short'); }, eeee: function eeee(s) { return s.format('day'); }, eeeee: function eeeee(s) { return s.format('day')[0]; }, //am/pm a: function a(s) { return s.ampm().toUpperCase(); }, aa: function aa(s) { return s.ampm().toUpperCase(); }, aaa: function aaa(s) { return s.ampm().toUpperCase(); }, aaaa: function aaaa(s) { return s.ampm().toUpperCase(); }, //hour h: function h(s) { return s.h12(); }, hh: function hh(s) { return pad(s.h12()); }, H: function H(s) { return s.hour(); }, HH: function HH(s) { return pad(s.hour()); }, // j: (s) => {},//weird hour format m: function m(s) { return s.minute(); }, mm: function mm(s) { return pad(s.minute()); }, s: function s(_s) { return _s.second(); }, ss: function ss(s) { return pad(s.second()); }, //milliseconds in the day A: function A(s) { return s.epoch - s.startOf('day').epoch; }, //timezone z: function z(s) { return s.timezone().name; }, zz: function zz(s) { return s.timezone().name; }, zzz: function zzz(s) { return s.timezone().name; }, zzzz: function zzzz(s) { return s.timezone().name; }, Z: function Z(s) { return s.timezone().current.offset + '00'; }, ZZ: function ZZ(s) { return s.timezone().current.offset + '00'; }, ZZZ: function ZZZ(s) { return s.timezone().current.offset + '00'; }, ZZZZ: function ZZZZ(s) { return s.timezone().current.offset + ':00'; } }; var addAlias = function addAlias(char, to, n) { var name = char; var toName = to; for (var i = 0; i < n; i += 1) { mapping[name] = mapping[toName]; name += char; toName += to; } }; addAlias('q', 'Q', 4); addAlias('L', 'M', 4); addAlias('Y', 'y', 4); addAlias('c', 'e', 4); addAlias('k', 'H', 2); addAlias('K', 'h', 2); addAlias('S', 's', 2); addAlias('v', 'z', 4); addAlias('V', 'Z', 4); var unixFmt = function unixFmt(s, str) { var chars = str.split(''); //combine consecutive chars, like 'yyyy' as one. var arr = [chars[0]]; var quoteOn = false; for (var i = 1; i < chars.length; i += 1) { //support quoted substrings if (chars[i] === "'") { quoteOn = !quoteOn; //support '', meaning one tick if (quoteOn === true && chars[i + 1] && chars[i + 1] === "'") { quoteOn = true; } else { continue; } } //merge it with the last one if (quoteOn === true || chars[i] === arr[arr.length - 1][0]) { arr[arr.length - 1] += chars[i]; } else { arr.push(chars[i]); } } return arr.reduce(function (txt, c) { if (mapping[c] !== undefined) { txt += mapping[c](s) || ''; } else { txt += c; } return txt; }, ''); }; module.exports = unixFmt; },{"../../fns":8}],22:[function(_dereq_,module,exports){ 'use strict'; var fns = _dereq_('../fns'); var days = _dereq_('../data/days'); var months = _dereq_('../data/months'); var addMethods = function addMethods(SpaceTime) { var methods = { i18n: function i18n(data) { if (!fns.isObject(data) || !fns.isObject(data.days) || !fns.isObject(data.months) || !fns.isArray(data.days.short) || !fns.isArray(data.days.long) || !fns.isArray(data.months.short) || !fns.isArray(data.months.long)) { throw new Error('Invalid i18n payload passed.'); } days.set(data.days); months.set(data.months); } }; //hook them into proto Object.keys(methods).forEach(function (k) { SpaceTime.prototype[k] = methods[k]; }); }; module.exports = addMethods; },{"../data/days":2,"../data/months":5,"../fns":8}],23:[function(_dereq_,module,exports){ 'use strict'; //round to either current, or +1 of this unit var nearest = function nearest(s, unit) { unit = unit.toLowerCase(); unit = unit.replace(/s$/, ''); //singular form... var prog = s.progress(); if (prog[unit] !== undefined) { if (prog[unit] > 0.5) { s = s.add(1, unit); } s = s.startOf(unit); } else if (s.silent === false) { console.warn("no known unit '" + unit + "'"); } return s; }; module.exports = nearest; },{}],24:[function(_dereq_,module,exports){ 'use strict'; //how far it is along, from 0-1 var progress = function progress(s) { var units = ['year', 'season', 'quarter', 'month', 'week', 'day', 'quarterHour', 'hour', 'minute']; var obj = {}; units.forEach(function (k) { var start = s.clone().startOf(k); var end = s.clone().endOf(k); var duration = end.epoch - start.epoch; var percent = (s.epoch - start.epoch) / duration; obj[k] = parseFloat(percent.toFixed(2)); }); return obj; }; module.exports = progress; },{}],25:[function(_dereq_,module,exports){ 'use strict'; var quarters = _dereq_('../../data/quarters'); var seasons = _dereq_('../../data/seasons'); var set = _dereq_('../set/set'); var fns = _dereq_('../../fns'); //destructive setters change the seconds, milliseconds, etc //- and not just the unit they're setting var clearMinutes = function clearMinutes(s) { s = s.minute(0); s = s.second(0); s = s.millisecond(1); return s; }; module.exports = { //some ambiguity here with 12/24h time: function time(str) { if (str !== undefined) { var s = this.clone(); s.epoch = set.time(s, str); return s; } return "".concat(this.h12(), ":").concat(fns.zeroPad(this.minute())).concat(this.ampm()); }, //since the start of the year week: function week(num) { if (num !== undefined) { var s = this.clone(); s = s.month(0); s = s.date(1); s = s.day('monday'); s = clearMinutes(s); //don't go into last-year if (s.monthName() === 'december') { s = s.add(1, 'week'); } num -= 1; //1-based s = s.add(num, 'weeks'); return s; } //find-out which week it is var tmp = this.clone(); tmp = tmp.month(0); tmp = tmp.date(1); tmp = clearMinutes(tmp); tmp = tmp.day('monday'); //don't go into last-year if (tmp.monthName() === 'december') { tmp = tmp.add(1, 'week'); } var thisOne = this.epoch; //if the week technically hasn't started yet if (tmp.epoch > thisOne) { return 1; } for (var i = 0; i < 52; i++) { if (tmp.epoch > thisOne) { return i; } tmp = tmp.add(1, 'week'); } return 52; }, quarter: function quarter(num) { if (num !== undefined) { if (typeof num === 'string') { num = num.replace(/^q/i, ''); num = parseInt(num, 10); } if (quarters[num]) { var s = this.clone(); var _month = quarters[num][0]; s = s.month(_month); s = s.date(1); s = s.startOf('day'); return s; } } var month = this.d.getMonth(); for (var i = 1; i < quarters.length; i++) { if (month < quarters[i][0]) { return i - 1; } } return 4; }, //'3:30' is 3.5 hourFloat: function hourFloat(num) { if (num !== undefined) { var s = this.clone(); var _minute = num % 1; _minute = _minute * 60; var _hour = parseInt(num, 10); s.epoch = set.hours(s, _hour); s.epoch = set.minutes(s, _minute); return s; } var d = this.d; var hour = d.getHours(); var minute = d.getMinutes(); minute = minute / 60; return hour + minute; }, season: function season(input) { var hem = 'north'; if (this.hemisphere() === 'South') { hem = 'south'; } if (input !== undefined) { var s = this.clone(); for (var i = 0; i < seasons[hem].length; i++) { if (input === seasons[hem][i][0]) { s = s.month(seasons[hem][i][1]); s = s.date(1); s = s.startOf('day'); } } return s; } var month = this.d.getMonth(); for (var _i = 0; _i < seasons[hem].length - 1; _i++) { if (month >= seasons[hem][_i][1] && month < seasons[hem][_i + 1][1]) { return seasons[hem][_i][0]; } } return 'winter'; } }; },{"../../data/quarters":6,"../../data/seasons":7,"../../fns":8,"../set/set":30}],26:[function(_dereq_,module,exports){ 'use strict'; var normal = _dereq_('./normal'); var destructive = _dereq_('./destructive'); var tricky = _dereq_('./tricky'); var addMethods = function addMethods(Space) { //hook the methods into prototype Object.keys(normal).forEach(function (k) { Space.prototype[k] = normal[k]; }); Object.keys(destructive).forEach(function (k) { Space.prototype[k] = destructive[k]; }); Object.keys(tricky).forEach(function (k) { Space.prototype[k] = tricky[k]; }); }; module.exports = addMethods; },{"./destructive":25,"./normal":27,"./tricky":28}],27:[function(_dereq_,module,exports){ 'use strict'; var set = _dereq_('../set/set'); var walkTo = _dereq_('../set/walk'); //the most basic get/set methods var methods = { millisecond: function millisecond(num) { if (num !== undefined) { var s = this.clone(); s.epoch = set.milliseconds(s, num); return s; } return this.d.getMilliseconds(); }, second: function second(num) { if (num !== undefined) { var s = this.clone(); s.epoch = set.seconds(s, num); return s; } return this.d.getSeconds(); }, minute: function minute(num) { if (num !== undefined) { var s = this.clone(); s.epoch = set.minutes(s, num); return s; } return this.d.getMinutes(); }, hour: function hour(num) { var d = this.d; if (num !== undefined) { var s = this.clone(); s.epoch = set.hours(s, num); walkTo(s, { month: this.month(), date: this.date(), hour: num }); return s; } return d.getHours(); }, hour12: function hour12(str) { var d = this.d; if (str !== undefined) { var s = this.clone(); str = '' + str; var m = str.match(/^([0-9]+)(am|pm)$/); if (m) { var hour = parseInt(m[1], 10); if (m[2] === 'pm') { hour += 12; } s.epoch = set.hours(s, hour); } return s; } //get the hour var hour12 = d.getHours(); if (hour12 > 12) { hour12 = hour12 - 12; } if (hour12 === 0) { hour12 = 12; } return hour12; }, date: function date(num) { if (num !== undefined) { var s = this.clone(); s.epoch = set.date(s, num); return s; } return this.d.getDate(); }, month: function month(input) { if (input !== undefined) { var s = this.clone(); s.epoch = set.month(s, input); return s; } return this.d.getMonth(); }, year: function year(num) { if (num !== undefined) { var s = this.clone(); s.epoch = set.year(s, num); return s; } return this.d.getFullYear(); }, iso: function iso(num) { if (num !== undefined) { return this.set(num); } return this.format('iso'); }, dayTime: function dayTime(str) { if (str !== undefined) { var times = { morning: '7:00am', breakfast: '7:00am', noon: '12:00am', lunch: '12:00pm', afternoon: '2:00pm', evening: '6:00pm', dinner: '6:00pm', night: '11:00pm', midnight: '23:59pm' }; var s = this