History

GSF.Web: Updated moment.js to reference the latest build to remove any known security vunerabilities.

Billy Ernest committed 8 years ago

Commit c94ec7e1 parent be1fbac2 files · +3947 −2454Browse files

Unified · Split

2 files
  1. Source/Libraries/GSF.Web/Shared/Scripts/moment.js +3946 −2453
  2. Source/package.json +1 −1
Source/Libraries/GSF.Web/Shared/Scripts/moment.js+3946−2453
@@ -1,538 +1,232 @@
11 //! moment.js
2−//! version : 2.9.0
2+//! version : 2.20.1
33 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
44 //! license : MIT
55 //! momentjs.com
66
7−(function (undefined) {
8− /************************************
9− Constants
10− ************************************/
11−
12− var moment,
13− VERSION = '2.9.0',
14− // the global-scope this is NOT the global object in Node.js
15− globalScope = (typeof global !== 'undefined' && (typeof window === 'undefined' || window === global.window)) ? global : this,
16− oldGlobalMoment,
17− round = Math.round,
18− hasOwnProperty = Object.prototype.hasOwnProperty,
19− i,
20−
21− YEAR = 0,
22− MONTH = 1,
23− DATE = 2,
24− HOUR = 3,
25− MINUTE = 4,
26− SECOND = 5,
27− MILLISECOND = 6,
28−
29− // internal storage for locale config files
30− locales = {},
31−
32− // extra moment internal properties (plugins register props here)
33− momentProperties = [],
34−
35− // check for nodeJS
36− hasModule = (typeof module !== 'undefined' && module && module.exports),
37−
38− // ASP.NET json date format regex
39− aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
40− aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
41−
42− // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
43− // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
44− isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
45−
46− // format tokens
47− formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,
48− localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
49−
50− // parsing token regexes
51− parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
52− parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
53− parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
54− parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
55− parseTokenDigits = /\d+/, // nonzero number of digits
56− parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
57− parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
58− parseTokenT = /T/i, // T (ISO separator)
59− parseTokenOffsetMs = /[\+\-]?\d+/, // 1234567890123
60− parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
61−
62− //strict parsing regexes
63− parseTokenOneDigit = /\d/, // 0 - 9
64− parseTokenTwoDigits = /\d\d/, // 00 - 99
65− parseTokenThreeDigits = /\d{3}/, // 000 - 999
66− parseTokenFourDigits = /\d{4}/, // 0000 - 9999
67− parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
68− parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
69−
70− // iso 8601 regex
71− // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
72− isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
73−
74− isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
75−
76− isoDates = [
77− ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
78− ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
79− ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
80− ['GGGG-[W]WW', /\d{4}-W\d{2}/],
81− ['YYYY-DDD', /\d{4}-\d{3}/]
82− ],
83−
84− // iso time formats and regexes
85− isoTimes = [
86− ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/],
87− ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
88− ['HH:mm', /(T| )\d\d:\d\d/],
89− ['HH', /(T| )\d\d/]
90− ],
91−
92− // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-', '15', '30']
93− parseTimezoneChunker = /([\+\-]|\d\d)/gi,
94−
95− // getter and setter names
96− proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
97− unitMillisecondFactors = {
98− 'Milliseconds' : 1,
99− 'Seconds' : 1e3,
100− 'Minutes' : 6e4,
101− 'Hours' : 36e5,
102− 'Days' : 864e5,
103− 'Months' : 2592e6,
104− 'Years' : 31536e6
105− },
106−
107− unitAliases = {
108− ms : 'millisecond',
109− s : 'second',
110− m : 'minute',
111− h : 'hour',
112− d : 'day',
113− D : 'date',
114− w : 'week',
115− W : 'isoWeek',
116− M : 'month',
117− Q : 'quarter',
118− y : 'year',
119− DDD : 'dayOfYear',
120− e : 'weekday',
121− E : 'isoWeekday',
122− gg: 'weekYear',
123− GG: 'isoWeekYear'
124− },
125−
126− camelFunctions = {
127− dayofyear : 'dayOfYear',
128− isoweekday : 'isoWeekday',
129− isoweek : 'isoWeek',
130− weekyear : 'weekYear',
131− isoweekyear : 'isoWeekYear'
132− },
133−
134− // format function strings
135− formatFunctions = {},
136−
137− // default relative time thresholds
138− relativeTimeThresholds = {
139− s: 45, // seconds to minute
140− m: 45, // minutes to hour
141− h: 22, // hours to day
142− d: 26, // days to month
143− M: 11 // months to year
144− },
145−
146− // tokens to ordinalize and pad
147− ordinalizeTokens = 'DDD w W M D d'.split(' '),
148− paddedTokens = 'M D H h m s w W'.split(' '),
149−
150− formatTokenFunctions = {
151− M : function () {
152− return this.month() + 1;
153− },
154− MMM : function (format) {
155− return this.localeData().monthsShort(this, format);
156− },
157− MMMM : function (format) {
158− return this.localeData().months(this, format);
159− },
160− D : function () {
161− return this.date();
162− },
163− DDD : function () {
164− return this.dayOfYear();
165− },
166− d : function () {
167− return this.day();
168− },
169− dd : function (format) {
170− return this.localeData().weekdaysMin(this, format);
171− },
172− ddd : function (format) {
173− return this.localeData().weekdaysShort(this, format);
174− },
175− dddd : function (format) {
176− return this.localeData().weekdays(this, format);
177− },
178− w : function () {
179− return this.week();
180− },
181− W : function () {
182− return this.isoWeek();
183− },
184− YY : function () {
185− return leftZeroFill(this.year() % 100, 2);
186− },
187− YYYY : function () {
188− return leftZeroFill(this.year(), 4);
189− },
190− YYYYY : function () {
191− return leftZeroFill(this.year(), 5);
192− },
193− YYYYYY : function () {
194− var y = this.year(), sign = y >= 0 ? '+' : '-';
195− return sign + leftZeroFill(Math.abs(y), 6);
196− },
197− gg : function () {
198− return leftZeroFill(this.weekYear() % 100, 2);
199− },
200− gggg : function () {
201− return leftZeroFill(this.weekYear(), 4);
202− },
203− ggggg : function () {
204− return leftZeroFill(this.weekYear(), 5);
205− },
206− GG : function () {
207− return leftZeroFill(this.isoWeekYear() % 100, 2);
208− },
209− GGGG : function () {
210− return leftZeroFill(this.isoWeekYear(), 4);
211− },
212− GGGGG : function () {
213− return leftZeroFill(this.isoWeekYear(), 5);
214− },
215− e : function () {
216− return this.weekday();
217− },
218− E : function () {
219− return this.isoWeekday();
220− },
221− a : function () {
222− return this.localeData().meridiem(this.hours(), this.minutes(), true);
223− },
224− A : function () {
225− return this.localeData().meridiem(this.hours(), this.minutes(), false);
226− },
227− H : function () {
228− return this.hours();
229− },
230− h : function () {
231− return this.hours() % 12 || 12;
232− },
233− m : function () {
234− return this.minutes();
235− },
236− s : function () {
237− return this.seconds();
238− },
239− S : function () {
240− return toInt(this.milliseconds() / 100);
241− },
242− SS : function () {
243− return leftZeroFill(toInt(this.milliseconds() / 10), 2);
244− },
245− SSS : function () {
246− return leftZeroFill(this.milliseconds(), 3);
247− },
248− SSSS : function () {
249− return leftZeroFill(this.milliseconds(), 3);
250− },
251− Z : function () {
252− var a = this.utcOffset(),
253− b = '+';
254− if (a < 0) {
255− a = -a;
256− b = '-';
257− }
258− return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);
259− },
260− ZZ : function () {
261− var a = this.utcOffset(),
262− b = '+';
263− if (a < 0) {
264− a = -a;
265− b = '-';
266− }
267− return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
268− },
269− z : function () {
270− return this.zoneAbbr();
271− },
272− zz : function () {
273− return this.zoneName();
274− },
275− x : function () {
276− return this.valueOf();
277− },
278− X : function () {
279− return this.unix();
280− },
281− Q : function () {
282− return this.quarter();
283− }
284− },
285−
286− deprecations = {},
7+; (function (global, factory) {
8+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9+ typeof define === 'function' && define.amd ? define(factory) :
10+ global.moment = factory()
11+}(this, (function () {
12+ 'use strict';
28713
288− lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'],
14+ var hookCallback;
28915
290− updateInProgress = false;
291−
292− // Pick the first defined of two or three arguments. dfl comes from
293− // default.
294− function dfl(a, b, c) {
295− switch (arguments.length) {
296− case 2: return a != null ? a : b;
297− case 3: return a != null ? a : b != null ? b : c;
298− default: throw new Error('Implement me');
299− }
16+ function hooks() {
17+ return hookCallback.apply(null, arguments);
30018 }
30119
302− function hasOwnProp(a, b) {
303− return hasOwnProperty.call(a, b);
20+ // This is done to register the method called with moment()
21+ // without creating circular dependencies.
22+ function setHookCallback(callback) {
23+ hookCallback = callback;
30424 }
30525
306− function defaultParsingFlags() {
307− // We need to deep clone this object, and es5 standard is not very
308− // helpful.
309− return {
310− empty : false,
311− unusedTokens : [],
312− unusedInput : [],
313− overflow : -2,
314− charsLeftOver : 0,
315− nullInput : false,
316− invalidMonth : null,
317− invalidFormat : false,
318− userInvalidated : false,
319− iso: false
320− };
26+ function isArray(input) {
27+ return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
32128 }
32229
323− function printMsg(msg) {
324− if (moment.suppressDeprecationWarnings === false &&
325− typeof console !== 'undefined' && console.warn) {
326− console.warn('Deprecation warning: ' + msg);
327− }
30+ function isObject(input) {
31+ // IE8 will treat undefined and null as object if it wasn't for
32+ // input != null
33+ return input != null && Object.prototype.toString.call(input) === '[object Object]';
32834 }
32935
330− function deprecate(msg, fn) {
331− var firstTime = true;
332− return extend(function () {
333− if (firstTime) {
334− printMsg(msg);
335− firstTime = false;
36+ function isObjectEmpty(obj) {
37+ if (Object.getOwnPropertyNames) {
38+ return (Object.getOwnPropertyNames(obj).length === 0);
39+ } else {
40+ var k;
41+ for (k in obj) {
42+ if (obj.hasOwnProperty(k)) {
43+ return false;
44+ }
33645 }
337− return fn.apply(this, arguments);
338− }, fn);
339− }
340−
341− function deprecateSimple(name, msg) {
342− if (!deprecations[name]) {
343− printMsg(msg);
344− deprecations[name] = true;
46+ return true;
34547 }
34648 }
34749
348− function padToken(func, count) {
349− return function (a) {
350− return leftZeroFill(func.call(this, a), count);
351− };
50+ function isUndefined(input) {
51+ return input === void 0;
35252 }
353− function ordinalizeToken(func, period) {
354− return function (a) {
355− return this.localeData().ordinal(func.call(this, a), period);
356− };
53+
54+ function isNumber(input) {
55+ return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
35756 }
35857
359− function monthDiff(a, b) {
360− // difference in months
361− var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
362− // b is in (anchor - 1 month, anchor + 1 month)
363− anchor = a.clone().add(wholeMonthDiff, 'months'),
364− anchor2, adjust;
58+ function isDate(input) {
59+ return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
60+ }
36561
366− if (b - anchor < 0) {
367− anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
368− // linear across the month
369− adjust = (b - anchor) / (anchor - anchor2);
370− } else {
371− anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
372− // linear across the month
373− adjust = (b - anchor) / (anchor2 - anchor);
62+ function map(arr, fn) {
63+ var res = [], i;
64+ for (i = 0; i < arr.length; ++i) {
65+ res.push(fn(arr[i], i));
37466 }
375−
376− return -(wholeMonthDiff + adjust);
67+ return res;
37768 }
37869
379− while (ordinalizeTokens.length) {
380− i = ordinalizeTokens.pop();
381− formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
382− }
383− while (paddedTokens.length) {
384− i = paddedTokens.pop();
385− formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
70+ function hasOwnProp(a, b) {
71+ return Object.prototype.hasOwnProperty.call(a, b);
38672 }
387− formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
38873
74+ function extend(a, b) {
75+ for (var i in b) {
76+ if (hasOwnProp(b, i)) {
77+ a[i] = b[i];
78+ }
79+ }
38980
390− function meridiemFixWrap(locale, hour, meridiem) {
391− var isPm;
392−
393− if (meridiem == null) {
394− // nothing to do
395− return hour;
81+ if (hasOwnProp(b, 'toString')) {
82+ a.toString = b.toString;
39683 }
397− if (locale.meridiemHour != null) {
398− return locale.meridiemHour(hour, meridiem);
399− } else if (locale.isPM != null) {
400− // Fallback
401− isPm = locale.isPM(meridiem);
402− if (isPm && hour < 12) {
403− hour += 12;
404− }
405− if (!isPm && hour === 12) {
406− hour = 0;
407− }
408− return hour;
409− } else {
410− // thie is not supposed to happen
411− return hour;
84+
85+ if (hasOwnProp(b, 'valueOf')) {
86+ a.valueOf = b.valueOf;
41287 }
88+
89+ return a;
41390 }
41491
415− /************************************
416− Constructors
417− ************************************/
92+ function createUTC(input, format, locale, strict) {
93+ return createLocalOrUTC(input, format, locale, strict, true).utc();
94+ }
41895
419− function Locale() {
96+ function defaultParsingFlags() {
97+ // We need to deep clone this object.
98+ return {
99+ empty: false,
100+ unusedTokens: [],
101+ unusedInput: [],
102+ overflow: -2,
103+ charsLeftOver: 0,
104+ nullInput: false,
105+ invalidMonth: null,
106+ invalidFormat: false,
107+ userInvalidated: false,
108+ iso: false,
109+ parsedDateParts: [],
110+ meridiem: null,
111+ rfc2822: false,
112+ weekdayMismatch: false
113+ };
420114 }
421115
422− // Moment prototype object
423− function Moment(config, skipOverflow) {
424− if (skipOverflow !== false) {
425− checkOverflow(config);
426− }
427− copyConfig(this, config);
428− this._d = new Date(+config._d);
429− // Prevent infinite loop in case updateOffset creates new moment
430− // objects.
431− if (updateInProgress === false) {
432− updateInProgress = true;
433− moment.updateOffset(this);
434− updateInProgress = false;
116+ function getParsingFlags(m) {
117+ if (m._pf == null) {
118+ m._pf = defaultParsingFlags();
435119 }
120+ return m._pf;
436121 }
437122
438− // Duration Constructor
439− function Duration(duration) {
440− var normalizedInput = normalizeObjectUnits(duration),
441− years = normalizedInput.year || 0,
442− quarters = normalizedInput.quarter || 0,
443− months = normalizedInput.month || 0,
444− weeks = normalizedInput.week || 0,
445− days = normalizedInput.day || 0,
446− hours = normalizedInput.hour || 0,
447− minutes = normalizedInput.minute || 0,
448− seconds = normalizedInput.second || 0,
449− milliseconds = normalizedInput.millisecond || 0;
450−
451− // representation for dateAddRemove
452− this._milliseconds = +milliseconds +
453− seconds * 1e3 + // 1000
454− minutes * 6e4 + // 1000 * 60
455− hours * 36e5; // 1000 * 60 * 60
456− // Because of dateAddRemove treats 24 hours as different from a
457− // day when working around DST, we need to store them separately
458− this._days = +days +
459− weeks * 7;
460− // It is impossible translate months into days without knowing
461− // which months you are are talking about, so we have to store
462− // it separately.
463− this._months = +months +
464− quarters * 3 +
465− years * 12;
466−
467− this._data = {};
123+ var some;
124+ if (Array.prototype.some) {
125+ some = Array.prototype.some;
126+ } else {
127+ some = function (fun) {
128+ var t = Object(this);
129+ var len = t.length >>> 0;
468130
469− this._locale = moment.localeData();
131+ for (var i = 0; i < len; i++) {
132+ if (i in t && fun.call(this, t[i], i, t)) {
133+ return true;
134+ }
135+ }
470136
471− this._bubble();
137+ return false;
138+ };
472139 }
473140
474− /************************************
475− Helpers
476− ************************************/
141+ function isValid(m) {
142+ if (m._isValid == null) {
143+ var flags = getParsingFlags(m);
144+ var parsedParts = some.call(flags.parsedDateParts, function (i) {
145+ return i != null;
146+ });
147+ var isNowValid = !isNaN(m._d.getTime()) &&
148+ flags.overflow < 0 &&
149+ !flags.empty &&
150+ !flags.invalidMonth &&
151+ !flags.invalidWeekday &&
152+ !flags.weekdayMismatch &&
153+ !flags.nullInput &&
154+ !flags.invalidFormat &&
155+ !flags.userInvalidated &&
156+ (!flags.meridiem || (flags.meridiem && parsedParts));
477157
158+ if (m._strict) {
159+ isNowValid = isNowValid &&
160+ flags.charsLeftOver === 0 &&
161+ flags.unusedTokens.length === 0 &&
162+ flags.bigHour === undefined;
163+ }
478164
479− function extend(a, b) {
480− for (var i in b) {
481− if (hasOwnProp(b, i)) {
482− a[i] = b[i];
165+ if (Object.isFrozen == null || !Object.isFrozen(m)) {
166+ m._isValid = isNowValid;
167+ }
168+ else {
169+ return isNowValid;
483170 }
484171 }
172+ return m._isValid;
173+ }
485174
486− if (hasOwnProp(b, 'toString')) {
487− a.toString = b.toString;
175+ function createInvalid(flags) {
176+ var m = createUTC(NaN);
177+ if (flags != null) {
178+ extend(getParsingFlags(m), flags);
488179 }
489−
490− if (hasOwnProp(b, 'valueOf')) {
491− a.valueOf = b.valueOf;
180+ else {
181+ getParsingFlags(m).userInvalidated = true;
492182 }
493183
494− return a;
184+ return m;
495185 }
496186
187+ // Plugins that add properties should also add the key here (null value),
188+ // so we can properly clone ourselves.
189+ var momentProperties = hooks.momentProperties = [];
190+
497191 function copyConfig(to, from) {
498192 var i, prop, val;
499193
500− if (typeof from._isAMomentObject !== 'undefined') {
194+ if (!isUndefined(from._isAMomentObject)) {
501195 to._isAMomentObject = from._isAMomentObject;
502196 }
503− if (typeof from._i !== 'undefined') {
197+ if (!isUndefined(from._i)) {
504198 to._i = from._i;
505199 }
506− if (typeof from._f !== 'undefined') {
200+ if (!isUndefined(from._f)) {
507201 to._f = from._f;
508202 }
509− if (typeof from._l !== 'undefined') {
203+ if (!isUndefined(from._l)) {
510204 to._l = from._l;
511205 }
512− if (typeof from._strict !== 'undefined') {
206+ if (!isUndefined(from._strict)) {
513207 to._strict = from._strict;
514208 }
515− if (typeof from._tzm !== 'undefined') {
209+ if (!isUndefined(from._tzm)) {
516210 to._tzm = from._tzm;
517211 }
518− if (typeof from._isUTC !== 'undefined') {
212+ if (!isUndefined(from._isUTC)) {
519213 to._isUTC = from._isUTC;
520214 }
521− if (typeof from._offset !== 'undefined') {
215+ if (!isUndefined(from._offset)) {
522216 to._offset = from._offset;
523217 }
524− if (typeof from._pf !== 'undefined') {
525− to._pf = from._pf;
218+ if (!isUndefined(from._pf)) {
219+ to._pf = getParsingFlags(from);
526220 }
527− if (typeof from._locale !== 'undefined') {
221+ if (!isUndefined(from._locale)) {
528222 to._locale = from._locale;
529223 }
530224
531225 if (momentProperties.length > 0) {
532− for (i in momentProperties) {
226+ for (i = 0; i < momentProperties.length; i++) {
533227 prop = momentProperties[i];
534228 val = from[prop];
535− if (typeof val !== 'undefined') {
229+ if (!isUndefined(val)) {
536230 to[prop] = val;
537231 }
538232 }
@@ -541,99 +235,46 @@ · 2 unmodified lines
541235 return to;
542236 }
543237
544− function absRound(number) {
545− if (number < 0) {
546− return Math.ceil(number);
547− } else {
548− return Math.floor(number);
549− }
550− }
551−
552− // left zero fill a number
553− // see http://jsperf.com/left-zero-filling for performance comparison
554− function leftZeroFill(number, targetLength, forceSign) {
555− var output = '' + Math.abs(number),
556− sign = number >= 0;
238+ var updateInProgress = false;
557239
558− while (output.length < targetLength) {
559− output = '0' + output;
240+ // Moment prototype object
241+ function Moment(config) {
242+ copyConfig(this, config);
243+ this._d = new Date(config._d != null ? config._d.getTime() : NaN);
244+ if (!this.isValid()) {
245+ this._d = new Date(NaN);
560246 }
561− return (sign ? (forceSign ? '+' : '') : '-') + output;
562− }
563−
564− function positiveMomentsDifference(base, other) {
565− var res = {milliseconds: 0, months: 0};
566−
567− res.months = other.month() - base.month() +
568− (other.year() - base.year()) * 12;
569− if (base.clone().add(res.months, 'M').isAfter(other)) {
570− --res.months;
247+ // Prevent infinite loop in case updateOffset creates new moment
248+ // objects.
249+ if (updateInProgress === false) {
250+ updateInProgress = true;
251+ hooks.updateOffset(this);
252+ updateInProgress = false;
571253 }
254+ }
572255
573− res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
574−
575− return res;
256+ function isMoment(obj) {
257+ return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
576258 }
577259
578− function momentsDifference(base, other) {
579− var res;
580− other = makeAs(other, base);
581− if (base.isBefore(other)) {
582− res = positiveMomentsDifference(base, other);
260+ function absFloor(number) {
261+ if (number < 0) {
262+ // -0 -> 0
263+ return Math.ceil(number) || 0;
583264 } else {
584− res = positiveMomentsDifference(other, base);
585− res.milliseconds = -res.milliseconds;
586− res.months = -res.months;
265+ return Math.floor(number);
587266 }
588−
589− return res;
590− }
591−
592− // TODO: remove 'name' arg after deprecation is removed
593− function createAdder(direction, name) {
594− return function (val, period) {
595− var dur, tmp;
596− //invert the arguments, but complain about it
597− if (period !== null && !isNaN(+period)) {
598− deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
599− tmp = val; val = period; period = tmp;
600− }
601−
602− val = typeof val === 'string' ? +val : val;
603− dur = moment.duration(val, period);
604− addOrSubtractDurationFromMoment(this, dur, direction);
605− return this;
606− };
607267 }
608268
609− function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
610− var milliseconds = duration._milliseconds,
611− days = duration._days,
612− months = duration._months;
613− updateOffset = updateOffset == null ? true : updateOffset;
269+ function toInt(argumentForCoercion) {
270+ var coercedNumber = +argumentForCoercion,
271+ value = 0;
614272
615− if (milliseconds) {
616− mom._d.setTime(+mom._d + milliseconds * isAdding);
617− }
618− if (days) {
619− rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);
620− }
621− if (months) {
622− rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);
623− }
624− if (updateOffset) {
625− moment.updateOffset(mom, days || months);
273+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
274+ value = absFloor(coercedNumber);
626275 }
627− }
628276
629− // check if is an array
630− function isArray(input) {
631− return Object.prototype.toString.call(input) === '[object Array]';
632− }
633−
634− function isDate(input) {
635− return Object.prototype.toString.call(input) === '[object Date]' ||
636− input instanceof Date;
277+ return value;
637278 }
638279
639280 // compare two arrays, return the number of differences
@@ -651,424 +292,295 @@ · 11 unmodified lines
651292 return diffs + lengthDiff;
652293 }
653294
654− function normalizeUnits(units) {
655− if (units) {
656− var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
657− units = unitAliases[units] || camelFunctions[lowered] || lowered;
295+ function warn(msg) {
296+ if (hooks.suppressDeprecationWarnings === false &&
297+ (typeof console !== 'undefined') && console.warn) {
298+ console.warn('Deprecation warning: ' + msg);
658299 }
659− return units;
660300 }
661301
662− function normalizeObjectUnits(inputObject) {
663− var normalizedInput = {},
664− normalizedProp,
665− prop;
302+ function deprecate(msg, fn) {
303+ var firstTime = true;
666304
667− for (prop in inputObject) {
668− if (hasOwnProp(inputObject, prop)) {
669− normalizedProp = normalizeUnits(prop);
670− if (normalizedProp) {
671− normalizedInput[normalizedProp] = inputObject[prop];
305+ return extend(function () {
306+ if (hooks.deprecationHandler != null) {
307+ hooks.deprecationHandler(null, msg);
308+ }
309+ if (firstTime) {
310+ var args = [];
311+ var arg;
312+ for (var i = 0; i < arguments.length; i++) {
313+ arg = '';
314+ if (typeof arguments[i] === 'object') {
315+ arg += '\n[' + i + '] ';
316+ for (var key in arguments[0]) {
317+ arg += key + ': ' + arguments[0][key] + ', ';
318+ }
319+ arg = arg.slice(0, -2); // Remove trailing comma and space
320+ } else {
321+ arg = arguments[i];
322+ }
323+ args.push(arg);
672324 }
325+ warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
326+ firstTime = false;
673327 }
674− }
675−
676− return normalizedInput;
328+ return fn.apply(this, arguments);
329+ }, fn);
677330 }
678331
679− function makeList(field) {
680− var count, setter;
332+ var deprecations = {};
681333
682− if (field.indexOf('week') === 0) {
683− count = 7;
684− setter = 'day';
334+ function deprecateSimple(name, msg) {
335+ if (hooks.deprecationHandler != null) {
336+ hooks.deprecationHandler(name, msg);
685337 }
686− else if (field.indexOf('month') === 0) {
687− count = 12;
688− setter = 'month';
689− }
690− else {
691− return;
338+ if (!deprecations[name]) {
339+ warn(msg);
340+ deprecations[name] = true;
692341 }
342+ }
693343
694− moment[field] = function (format, index) {
695− var i, getter,
696− method = moment._locale[field],
697− results = [];
698−
699− if (typeof format === 'number') {
700− index = format;
701− format = undefined;
702− }
703−
704− getter = function (i) {
705− var m = moment().utc().set(setter, i);
706− return method.call(moment._locale, m, format || '');
707− };
344+ hooks.suppressDeprecationWarnings = false;
345+ hooks.deprecationHandler = null;
708346
709− if (index != null) {
710− return getter(index);
711− }
712− else {
713− for (i = 0; i < count; i++) {
714− results.push(getter(i));
715− }
716− return results;
717− }
718− };
347+ function isFunction(input) {
348+ return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
719349 }
720350
721− function toInt(argumentForCoercion) {
722− var coercedNumber = +argumentForCoercion,
723− value = 0;
724−
725− if (coercedNumber !== 0 && isFinite(coercedNumber)) {
726− if (coercedNumber >= 0) {
727− value = Math.floor(coercedNumber);
351+ function set(config) {
352+ var prop, i;
353+ for (i in config) {
354+ prop = config[i];
355+ if (isFunction(prop)) {
356+ this[i] = prop;
728357 } else {
729− value = Math.ceil(coercedNumber);
358+ this['_' + i] = prop;
730359 }
731360 }
732−
733− return value;
361+ this._config = config;
362+ // Lenient ordinal parsing accepts just a number in addition to
363+ // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
364+ // TODO: Remove "ordinalParse" fallback in next major release.
365+ this._dayOfMonthOrdinalParseLenient = new RegExp(
366+ (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
367+ '|' + (/\d{1,2}/).source);
734368 }
735369
736− function daysInMonth(year, month) {
737− return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
370+ function mergeConfigs(parentConfig, childConfig) {
371+ var res = extend({}, parentConfig), prop;
372+ for (prop in childConfig) {
373+ if (hasOwnProp(childConfig, prop)) {
374+ if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
375+ res[prop] = {};
376+ extend(res[prop], parentConfig[prop]);
377+ extend(res[prop], childConfig[prop]);
378+ } else if (childConfig[prop] != null) {
379+ res[prop] = childConfig[prop];
380+ } else {
381+ delete res[prop];
382+ }
383+ }
384+ }
385+ for (prop in parentConfig) {
386+ if (hasOwnProp(parentConfig, prop) &&
387+ !hasOwnProp(childConfig, prop) &&
388+ isObject(parentConfig[prop])) {
389+ // make sure changes to properties don't modify parent config
390+ res[prop] = extend({}, res[prop]);
391+ }
392+ }
393+ return res;
738394 }
739395
740− function weeksInYear(year, dow, doy) {
741− return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;
396+ function Locale(config) {
397+ if (config != null) {
398+ this.set(config);
399+ }
742400 }
743401
744− function daysInYear(year) {
745− return isLeapYear(year) ? 366 : 365;
402+ var keys;
403+
404+ if (Object.keys) {
405+ keys = Object.keys;
406+ } else {
407+ keys = function (obj) {
408+ var i, res = [];
409+ for (i in obj) {
410+ if (hasOwnProp(obj, i)) {
411+ res.push(i);
412+ }
413+ }
414+ return res;
415+ };
746416 }
747417
748− function isLeapYear(year) {
749− return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
418+ var defaultCalendar = {
419+ sameDay: '[Today at] LT',
420+ nextDay: '[Tomorrow at] LT',
421+ nextWeek: 'dddd [at] LT',
422+ lastDay: '[Yesterday at] LT',
423+ lastWeek: '[Last] dddd [at] LT',
424+ sameElse: 'L'
425+ };
426+
427+ function calendar(key, mom, now) {
428+ var output = this._calendar[key] || this._calendar['sameElse'];
429+ return isFunction(output) ? output.call(mom, now) : output;
750430 }
751431
752− function checkOverflow(m) {
753− var overflow;
754− if (m._a && m._pf.overflow === -2) {
755− overflow =
756− m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
757− m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
758− m._a[HOUR] < 0 || m._a[HOUR] > 24 ||
759− (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||
760− m._a[SECOND] !== 0 ||
761− m._a[MILLISECOND] !== 0)) ? HOUR :
762− m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
763− m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
764− m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
765− -1;
432+ var defaultLongDateFormat = {
433+ LTS: 'h:mm:ss A',
434+ LT: 'h:mm A',
435+ L: 'MM/DD/YYYY',
436+ LL: 'MMMM D, YYYY',
437+ LLL: 'MMMM D, YYYY h:mm A',
438+ LLLL: 'dddd, MMMM D, YYYY h:mm A'
439+ };
766440
767− if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
768− overflow = DATE;
769− }
441+ function longDateFormat(key) {
442+ var format = this._longDateFormat[key],
443+ formatUpper = this._longDateFormat[key.toUpperCase()];
770444
771− m._pf.overflow = overflow;
445+ if (format || !formatUpper) {
446+ return format;
772447 }
773− }
774448
775− function isValid(m) {
776− if (m._isValid == null) {
777− m._isValid = !isNaN(m._d.getTime()) &&
778− m._pf.overflow < 0 &&
779− !m._pf.empty &&
780− !m._pf.invalidMonth &&
781− !m._pf.nullInput &&
782− !m._pf.invalidFormat &&
783− !m._pf.userInvalidated;
449+ this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
450+ return val.slice(1);
451+ });
784452
785− if (m._strict) {
786− m._isValid = m._isValid &&
787− m._pf.charsLeftOver === 0 &&
788− m._pf.unusedTokens.length === 0 &&
789− m._pf.bigHour === undefined;
790− }
791− }
792− return m._isValid;
453+ return this._longDateFormat[key];
793454 }
794455
795− function normalizeLocale(key) {
796− return key ? key.toLowerCase().replace('_', '-') : key;
456+ var defaultInvalidDate = 'Invalid date';
457+
458+ function invalidDate() {
459+ return this._invalidDate;
797460 }
798461
799− // pick the locale from the array
800− // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
801− // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
802− function chooseLocale(names) {
803− var i = 0, j, next, locale, split;
462+ var defaultOrdinal = '%d';
463+ var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
804464
805− while (i < names.length) {
806− split = normalizeLocale(names[i]).split('-');
807− j = split.length;
808− next = normalizeLocale(names[i + 1]);
809− next = next ? next.split('-') : null;
810− while (j > 0) {
811− locale = loadLocale(split.slice(0, j).join('-'));
812− if (locale) {
813− return locale;
814− }
815− if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
816− //the next array item is better than a shallower substring of this one
817− break;
818− }
819− j--;
820− }
821− i++;
822− }
823− return null;
465+ function ordinal(number) {
466+ return this._ordinal.replace('%d', number);
824467 }
825468
826− function loadLocale(name) {
827− var oldLocale = null;
828− if (!locales[name] && hasModule) {
829− try {
830− oldLocale = moment.locale();
831− require('./locale/' + name);
832− // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales
833− moment.locale(oldLocale);
834− } catch (e) { }
835− }
836− return locales[name];
469+ var defaultRelativeTime = {
470+ future: 'in %s',
471+ past: '%s ago',
472+ s: 'a few seconds',
473+ ss: '%d seconds',
474+ m: 'a minute',
475+ mm: '%d minutes',
476+ h: 'an hour',
477+ hh: '%d hours',
478+ d: 'a day',
479+ dd: '%d days',
480+ M: 'a month',
481+ MM: '%d months',
482+ y: 'a year',
483+ yy: '%d years'
484+ };
485+
486+ function relativeTime(number, withoutSuffix, string, isFuture) {
487+ var output = this._relativeTime[string];
488+ return (isFunction(output)) ?
489+ output(number, withoutSuffix, string, isFuture) :
490+ output.replace(/%d/i, number);
837491 }
838492
839− // Return a moment from input, that is local/utc/utcOffset equivalent to
840− // model.
841− function makeAs(input, model) {
842− var res, diff;
843− if (model._isUTC) {
844− res = model.clone();
845− diff = (moment.isMoment(input) || isDate(input) ?
846− +input : +moment(input)) - (+res);
847− // Use low-level api, because this fn is low-level api.
848− res._d.setTime(+res._d + diff);
849− moment.updateOffset(res, false);
850− return res;
851− } else {
852− return moment(input).local();
853− }
493+ function pastFuture(diff, output) {
494+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
495+ return isFunction(format) ? format(output) : format.replace(/%s/i, output);
854496 }
855497
856− /************************************
857− Locale
858− ************************************/
498+ var aliases = {};
499+
500+ function addUnitAlias(unit, shorthand) {
501+ var lowerCase = unit.toLowerCase();
502+ aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
503+ }
859504
505+ function normalizeUnits(units) {
506+ return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
507+ }
860508
861− extend(Locale.prototype, {
509+ function normalizeObjectUnits(inputObject) {
510+ var normalizedInput = {},
511+ normalizedProp,
512+ prop;
862513
863− set : function (config) {
864− var prop, i;
865− for (i in config) {
866− prop = config[i];
867− if (typeof prop === 'function') {
868− this[i] = prop;
869− } else {
870− this['_' + i] = prop;
514+ for (prop in inputObject) {
515+ if (hasOwnProp(inputObject, prop)) {
516+ normalizedProp = normalizeUnits(prop);
517+ if (normalizedProp) {
518+ normalizedInput[normalizedProp] = inputObject[prop];
871519 }
872520 }
873− // Lenient ordinal parsing accepts just a number in addition to
874− // number + (possibly) stuff coming from _ordinalParseLenient.
875− this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\d{1,2}/.source);
876− },
877−
878− _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
879− months : function (m) {
880− return this._months[m.month()];
881− },
521+ }
882522
883− _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
884− monthsShort : function (m) {
885− return this._monthsShort[m.month()];
886− },
523+ return normalizedInput;
524+ }
887525
888− monthsParse : function (monthName, format, strict) {
889− var i, mom, regex;
526+ var priorities = {};
890527
891− if (!this._monthsParse) {
892− this._monthsParse = [];
893− this._longMonthsParse = [];
894− this._shortMonthsParse = [];
895− }
528+ function addUnitPriority(unit, priority) {
529+ priorities[unit] = priority;
530+ }
896531
897− for (i = 0; i < 12; i++) {
898− // make the regex if we don't have it already
899− mom = moment.utc([2000, i]);
900− if (strict && !this._longMonthsParse[i]) {
901− this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
902− this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
903− }
904− if (!strict && !this._monthsParse[i]) {
905− regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
906− this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
907− }
908− // test the regex
909− if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
910− return i;
911− } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
912− return i;
913− } else if (!strict && this._monthsParse[i].test(monthName)) {
914− return i;
915− }
916− }
917− },
532+ function getPrioritizedUnits(unitsObj) {
533+ var units = [];
534+ for (var u in unitsObj) {
535+ units.push({ unit: u, priority: priorities[u] });
536+ }
537+ units.sort(function (a, b) {
538+ return a.priority - b.priority;
539+ });
540+ return units;
541+ }
918542
919− _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
920− weekdays : function (m) {
921− return this._weekdays[m.day()];
922− },
543+ function zeroFill(number, targetLength, forceSign) {
544+ var absNumber = '' + Math.abs(number),
545+ zerosToFill = targetLength - absNumber.length,
546+ sign = number >= 0;
547+ return (sign ? (forceSign ? '+' : '') : '-') +
548+ Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
549+ }
923550
924− _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
925− weekdaysShort : function (m) {
926− return this._weekdaysShort[m.day()];
927− },
551+ var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
928552
929− _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
930− weekdaysMin : function (m) {
931− return this._weekdaysMin[m.day()];
932− },
553+ var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
933554
934− weekdaysParse : function (weekdayName) {
935− var i, mom, regex;
555+ var formatFunctions = {};
936556
937− if (!this._weekdaysParse) {
938− this._weekdaysParse = [];
939− }
557+ var formatTokenFunctions = {};
940558
941− for (i = 0; i < 7; i++) {
942− // make the regex if we don't have it already
943− if (!this._weekdaysParse[i]) {
944− mom = moment([2000, 1]).day(i);
945− regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
946− this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
947− }
948− // test the regex
949− if (this._weekdaysParse[i].test(weekdayName)) {
950− return i;
951− }
952− }
953− },
954−
955− _longDateFormat : {
956− LTS : 'h:mm:ss A',
957− LT : 'h:mm A',
958− L : 'MM/DD/YYYY',
959− LL : 'MMMM D, YYYY',
960− LLL : 'MMMM D, YYYY LT',
961− LLLL : 'dddd, MMMM D, YYYY LT'
962− },
963− longDateFormat : function (key) {
964− var output = this._longDateFormat[key];
965− if (!output && this._longDateFormat[key.toUpperCase()]) {
966− output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
967− return val.slice(1);
968− });
969− this._longDateFormat[key] = output;
970− }
971− return output;
972− },
973−
974− isPM : function (input) {
975− // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
976− // Using charAt should be more compatible.
977− return ((input + '').toLowerCase().charAt(0) === 'p');
978− },
979−
980− _meridiemParse : /[ap]\.?m?\.?/i,
981− meridiem : function (hours, minutes, isLower) {
982− if (hours > 11) {
983− return isLower ? 'pm' : 'PM';
984− } else {
985− return isLower ? 'am' : 'AM';
986− }
987− },
988−
989−
990− _calendar : {
991− sameDay : '[Today at] LT',
992− nextDay : '[Tomorrow at] LT',
993− nextWeek : 'dddd [at] LT',
994− lastDay : '[Yesterday at] LT',
995− lastWeek : '[Last] dddd [at] LT',
996− sameElse : 'L'
997− },
998− calendar : function (key, mom, now) {
999− var output = this._calendar[key];
1000− return typeof output === 'function' ? output.apply(mom, [now]) : output;
1001− },
1002−
1003− _relativeTime : {
1004− future : 'in %s',
1005− past : '%s ago',
1006− s : 'a few seconds',
1007− m : 'a minute',
1008− mm : '%d minutes',
1009− h : 'an hour',
1010− hh : '%d hours',
1011− d : 'a day',
1012− dd : '%d days',
1013− M : 'a month',
1014− MM : '%d months',
1015− y : 'a year',
1016− yy : '%d years'
1017− },
1018−
1019− relativeTime : function (number, withoutSuffix, string, isFuture) {
1020− var output = this._relativeTime[string];
1021− return (typeof output === 'function') ?
1022− output(number, withoutSuffix, string, isFuture) :
1023− output.replace(/%d/i, number);
1024− },
1025−
1026− pastFuture : function (diff, output) {
1027− var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
1028− return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
1029− },
1030−
1031− ordinal : function (number) {
1032− return this._ordinal.replace('%d', number);
1033− },
1034− _ordinal : '%d',
1035− _ordinalParse : /\d{1,2}/,
1036−
1037− preparse : function (string) {
1038− return string;
1039− },
1040−
1041− postformat : function (string) {
1042− return string;
1043− },
1044−
1045− week : function (mom) {
1046− return weekOfYear(mom, this._week.dow, this._week.doy).week;
1047− },
1048−
1049− _week : {
1050− dow : 0, // Sunday is the first day of the week.
1051− doy : 6 // The week that contains Jan 1st is the first week of the year.
1052− },
1053−
1054− firstDayOfWeek : function () {
1055− return this._week.dow;
1056− },
1057−
1058− firstDayOfYear : function () {
1059− return this._week.doy;
1060− },
1061−
1062− _invalidDate: 'Invalid date',
1063− invalidDate: function () {
1064− return this._invalidDate;
559+ // token: 'M'
560+ // padded: ['MM', 2]
561+ // ordinal: 'Mo'
562+ // callback: function () { this.month() + 1 }
563+ function addFormatToken(token, padded, ordinal, callback) {
564+ var func = callback;
565+ if (typeof callback === 'string') {
566+ func = function () {
567+ return this[callback]();
568+ };
1065569 }
1066− });
1067−
1068− /************************************
1069− Formatting
1070− ************************************/
1071−
570+ if (token) {
571+ formatTokenFunctions[token] = func;
572+ }
573+ if (padded) {
574+ formatTokenFunctions[padded[0]] = function () {
575+ return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
576+ };
577+ }
578+ if (ordinal) {
579+ formatTokenFunctions[ordinal] = function () {
580+ return this.localeData().ordinal(func.apply(this, arguments), token);
581+ };
582+ }
583+ }
1072584
1073585 function removeFormattingTokens(input) {
1074586 if (input.match(/\[[\s\S]/)) {
@@ -1089,9 +601,9 @@ · 14 unmodified lines
1089601 }
1090602
1091603 return function (mom) {
1092− var output = '';
604+ var output = '', i;
1093605 for (i = 0; i < length; i++) {
1094− output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
606+ output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
1095607 }
1096608 return output;
1097609 };
@@ -1104,10 +616,7 @@ · 6 unmodified lines
1104616 }
1105617
1106618 format = expandFormat(format, m.localeData());
1107−
1108− if (!formatFunctions[format]) {
1109− formatFunctions[format] = makeFormatFunction(format);
1110− }
619+ formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
1111620
1112621 return formatFunctions[format](m);
1113622 }
@@ -1129,982 +638,1278 @@ · 15 unmodified lines
1129638 return format;
1130639 }
1131640
641+ var match1 = /\d/; // 0 - 9
642+ var match2 = /\d\d/; // 00 - 99
643+ var match3 = /\d{3}/; // 000 - 999
644+ var match4 = /\d{4}/; // 0000 - 9999
645+ var match6 = /[+-]?\d{6}/; // -999999 - 999999
646+ var match1to2 = /\d\d?/; // 0 - 99
647+ var match3to4 = /\d\d\d\d?/; // 999 - 9999
648+ var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
649+ var match1to3 = /\d{1,3}/; // 0 - 999
650+ var match1to4 = /\d{1,4}/; // 0 - 9999
651+ var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
652+
653+ var matchUnsigned = /\d+/; // 0 - inf
654+ var matchSigned = /[+-]?\d+/; // -inf - inf
655+
656+ var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
657+ var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
658+
659+ var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
1132660
1133− /************************************
1134− Parsing
1135− ************************************/
661+ // any word (or two) characters or numbers including two/three word month in arabic.
662+ // includes scottish gaelic two word and hyphenated months
663+ var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
1136664
1137665
1138− // get the regex to find the next token
666+ var regexes = {};
667+
668+ function addRegexToken(token, regex, strictRegex) {
669+ regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
670+ return (isStrict && strictRegex) ? strictRegex : regex;
671+ };
672+ }
673+
1139674 function getParseRegexForToken(token, config) {
1140− var a, strict = config._strict;
1141− switch (token) {
1142− case 'Q':
1143− return parseTokenOneDigit;
1144− case 'DDDD':
1145− return parseTokenThreeDigits;
1146− case 'YYYY':
1147− case 'GGGG':
1148− case 'gggg':
1149− return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
1150− case 'Y':
1151− case 'G':
1152− case 'g':
1153− return parseTokenSignedNumber;
1154− case 'YYYYYY':
1155− case 'YYYYY':
1156− case 'GGGGG':
1157− case 'ggggg':
1158− return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
1159− case 'S':
1160− if (strict) {
1161− return parseTokenOneDigit;
1162− }
1163− /* falls through */
1164− case 'SS':
1165− if (strict) {
1166− return parseTokenTwoDigits;
1167− }
1168− /* falls through */
1169− case 'SSS':
1170− if (strict) {
1171− return parseTokenThreeDigits;
1172− }
1173− /* falls through */
1174− case 'DDD':
1175− return parseTokenOneToThreeDigits;
1176− case 'MMM':
1177− case 'MMMM':
1178− case 'dd':
1179− case 'ddd':
1180− case 'dddd':
1181− return parseTokenWord;
1182− case 'a':
1183− case 'A':
1184− return config._locale._meridiemParse;
1185− case 'x':
1186− return parseTokenOffsetMs;
1187− case 'X':
1188− return parseTokenTimestampMs;
1189− case 'Z':
1190− case 'ZZ':
1191− return parseTokenTimezone;
1192− case 'T':
1193− return parseTokenT;
1194− case 'SSSS':
1195− return parseTokenDigits;
1196− case 'MM':
1197− case 'DD':
1198− case 'YY':
1199− case 'GG':
1200− case 'gg':
1201− case 'HH':
1202− case 'hh':
1203− case 'mm':
1204− case 'ss':
1205− case 'ww':
1206− case 'WW':
1207− return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
1208− case 'M':
1209− case 'D':
1210− case 'd':
1211− case 'H':
1212− case 'h':
1213− case 'm':
1214− case 's':
1215− case 'w':
1216− case 'W':
1217− case 'e':
1218− case 'E':
1219− return parseTokenOneOrTwoDigits;
1220− case 'Do':
1221− return strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient;
1222− default :
1223− a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
1224− return a;
675+ if (!hasOwnProp(regexes, token)) {
676+ return new RegExp(unescapeFormat(token));
1225677 }
678+
679+ return regexes[token](config._strict, config._locale);
1226680 }
1227681
1228− function utcOffsetFromString(string) {
1229− string = string || '';
1230− var possibleTzMatches = (string.match(parseTokenTimezone) || []),
1231− tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
1232− parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
1233− minutes = +(parts[1] * 60) + toInt(parts[2]);
682+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
683+ function unescapeFormat(s) {
684+ return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
685+ return p1 || p2 || p3 || p4;
686+ }));
687+ }
1234688
1235− return parts[0] === '+' ? minutes : -minutes;
689+ function regexEscape(s) {
690+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1236691 }
1237692
1238− // function to convert string input to date
1239− function addTimeToArrayFromToken(token, input, config) {
1240− var a, datePartArray = config._a;
1241−
1242− switch (token) {
1243− // QUARTER
1244− case 'Q':
1245− if (input != null) {
1246− datePartArray[MONTH] = (toInt(input) - 1) * 3;
1247− }
1248− break;
1249− // MONTH
1250− case 'M' : // fall through to MM
1251− case 'MM' :
1252− if (input != null) {
1253− datePartArray[MONTH] = toInt(input) - 1;
1254− }
1255− break;
1256− case 'MMM' : // fall through to MMMM
1257− case 'MMMM' :
1258− a = config._locale.monthsParse(input, token, config._strict);
1259− // if we didn't find a month name, mark the date as invalid.
1260− if (a != null) {
1261− datePartArray[MONTH] = a;
1262− } else {
1263− config._pf.invalidMonth = input;
1264− }
1265− break;
1266− // DAY OF MONTH
1267− case 'D' : // fall through to DD
1268− case 'DD' :
1269− if (input != null) {
1270− datePartArray[DATE] = toInt(input);
1271− }
1272− break;
1273− case 'Do' :
1274− if (input != null) {
1275− datePartArray[DATE] = toInt(parseInt(
1276− input.match(/\d{1,2}/)[0], 10));
1277− }
1278− break;
1279− // DAY OF YEAR
1280− case 'DDD' : // fall through to DDDD
1281− case 'DDDD' :
1282− if (input != null) {
1283− config._dayOfYear = toInt(input);
1284− }
1285−
1286− break;
1287− // YEAR
1288− case 'YY' :
1289− datePartArray[YEAR] = moment.parseTwoDigitYear(input);
1290− break;
1291− case 'YYYY' :
1292− case 'YYYYY' :
1293− case 'YYYYYY' :
1294− datePartArray[YEAR] = toInt(input);
1295− break;
1296− // AM / PM
1297− case 'a' : // fall through to A
1298− case 'A' :
1299− config._meridiem = input;
1300− // config._isPm = config._locale.isPM(input);
1301− break;
1302− // HOUR
1303− case 'h' : // fall through to hh
1304− case 'hh' :
1305− config._pf.bigHour = true;
1306− /* falls through */
1307− case 'H' : // fall through to HH
1308− case 'HH' :
1309− datePartArray[HOUR] = toInt(input);
1310− break;
1311− // MINUTE
1312− case 'm' : // fall through to mm
1313− case 'mm' :
1314− datePartArray[MINUTE] = toInt(input);
1315− break;
1316− // SECOND
1317− case 's' : // fall through to ss
1318− case 'ss' :
1319− datePartArray[SECOND] = toInt(input);
1320− break;
1321− // MILLISECOND
1322− case 'S' :
1323− case 'SS' :
1324− case 'SSS' :
1325− case 'SSSS' :
1326− datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
1327− break;
1328− // UNIX OFFSET (MILLISECONDS)
1329− case 'x':
1330− config._d = new Date(toInt(input));
1331− break;
1332− // UNIX TIMESTAMP WITH MS
1333− case 'X':
1334− config._d = new Date(parseFloat(input) * 1000);
1335− break;
1336− // TIMEZONE
1337− case 'Z' : // fall through to ZZ
1338− case 'ZZ' :
1339− config._useUTC = true;
1340− config._tzm = utcOffsetFromString(input);
1341− break;
1342− // WEEKDAY - human
1343− case 'dd':
1344− case 'ddd':
1345− case 'dddd':
1346− a = config._locale.weekdaysParse(input);
1347− // if we didn't get a weekday name, mark the date as invalid
1348− if (a != null) {
1349− config._w = config._w || {};
1350− config._w['d'] = a;
1351− } else {
1352− config._pf.invalidWeekday = input;
1353− }
1354− break;
1355− // WEEK, WEEK DAY - numeric
1356− case 'w':
1357− case 'ww':
1358− case 'W':
1359− case 'WW':
1360− case 'd':
1361− case 'e':
1362− case 'E':
1363− token = token.substr(0, 1);
1364− /* falls through */
1365− case 'gggg':
1366− case 'GGGG':
1367− case 'GGGGG':
1368− token = token.substr(0, 2);
1369− if (input) {
1370− config._w = config._w || {};
1371− config._w[token] = toInt(input);
1372− }
1373− break;
1374− case 'gg':
1375− case 'GG':
693+ var tokens = {};
694+
695+ function addParseToken(token, callback) {
696+ var i, func = callback;
697+ if (typeof token === 'string') {
698+ token = [token];
699+ }
700+ if (isNumber(callback)) {
701+ func = function (input, array) {
702+ array[callback] = toInt(input);
703+ };
704+ }
705+ for (i = 0; i < token.length; i++) {
706+ tokens[token[i]] = func;
707+ }
708+ }
709+
710+ function addWeekParseToken(token, callback) {
711+ addParseToken(token, function (input, array, config, token) {
1376712 config._w = config._w || {};
1377− config._w[token] = moment.parseTwoDigitYear(input);
713+ callback(input, config._w, config, token);
714+ });
715+ }
716+
717+ function addTimeToArrayFromToken(token, input, config) {
718+ if (input != null && hasOwnProp(tokens, token)) {
719+ tokens[token](input, config._a, config, token);
1378720 }
1379721 }
1380722
1381− function dayOfYearFromWeekInfo(config) {
1382− var w, weekYear, week, weekday, dow, doy, temp;
723+ var YEAR = 0;
724+ var MONTH = 1;
725+ var DATE = 2;
726+ var HOUR = 3;
727+ var MINUTE = 4;
728+ var SECOND = 5;
729+ var MILLISECOND = 6;
730+ var WEEK = 7;
731+ var WEEKDAY = 8;
732+
733+ // FORMATTING
734+
735+ addFormatToken('Y', 0, 0, function () {
736+ var y = this.year();
737+ return y <= 9999 ? '' + y : '+' + y;
738+ });
1383739
1384− w = config._w;
1385− if (w.GG != null || w.W != null || w.E != null) {
1386− dow = 1;
1387− doy = 4;
740+ addFormatToken(0, ['YY', 2], 0, function () {
741+ return this.year() % 100;
742+ });
1388743
1389− // TODO: We need to take the current isoWeekYear, but that depends on
1390− // how we interpret now (local, utc, fixed offset). So create
1391− // a now version of current config (take local/utc/offset flags, and
1392− // create now).
1393− weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year);
1394− week = dfl(w.W, 1);
1395− weekday = dfl(w.E, 1);
1396− } else {
1397− dow = config._locale._week.dow;
1398− doy = config._locale._week.doy;
744+ addFormatToken(0, ['YYYY', 4], 0, 'year');
745+ addFormatToken(0, ['YYYYY', 5], 0, 'year');
746+ addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
1399747
1400− weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);
1401− week = dfl(w.w, 1);
748+ // ALIASES
1402749
1403− if (w.d != null) {
1404− // weekday -- low day numbers are considered next week
1405− weekday = w.d;
1406− if (weekday < dow) {
1407− ++week;
1408− }
1409− } else if (w.e != null) {
1410− // local weekday -- counting starts from begining of week
1411− weekday = w.e + dow;
1412− } else {
1413− // default to begining of week
1414− weekday = dow;
1415− }
1416− }
1417− temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
750+ addUnitAlias('year', 'y');
751+
752+ // PRIORITIES
753+
754+ addUnitPriority('year', 1);
755+
756+ // PARSING
757+
758+ addRegexToken('Y', matchSigned);
759+ addRegexToken('YY', match1to2, match2);
760+ addRegexToken('YYYY', match1to4, match4);
761+ addRegexToken('YYYYY', match1to6, match6);
762+ addRegexToken('YYYYYY', match1to6, match6);
763+
764+ addParseToken(['YYYYY', 'YYYYYY'], YEAR);
765+ addParseToken('YYYY', function (input, array) {
766+ array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
767+ });
768+ addParseToken('YY', function (input, array) {
769+ array[YEAR] = hooks.parseTwoDigitYear(input);
770+ });
771+ addParseToken('Y', function (input, array) {
772+ array[YEAR] = parseInt(input, 10);
773+ });
774+
775+ // HELPERS
1418776
1419− config._a[YEAR] = temp.year;
1420− config._dayOfYear = temp.dayOfYear;
777+ function daysInYear(year) {
778+ return isLeapYear(year) ? 366 : 365;
1421779 }
1422780
1423− // convert an array to a date.
1424− // the array should mirror the parameters below
1425− // note: all values past the year are optional and will default to the lowest possible value.
1426− // [year, month, day , hour, minute, second, millisecond]
1427− function dateFromConfig(config) {
1428− var i, date, input = [], currentDate, yearToUse;
781+ function isLeapYear(year) {
782+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
783+ }
1429784
1430− if (config._d) {
1431− return;
1432− }
785+ // HOOKS
1433786
1434− currentDate = currentDateArray(config);
787+ hooks.parseTwoDigitYear = function (input) {
788+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
789+ };
1435790
1436− //compute day of the year from weeks and weekdays
1437− if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1438− dayOfYearFromWeekInfo(config);
1439− }
791+ // MOMENTS
1440792
1441− //if the day of the year is set, figure out what it is
1442− if (config._dayOfYear) {
1443− yearToUse = dfl(config._a[YEAR], currentDate[YEAR]);
793+ var getSetYear = makeGetSet('FullYear', true);
1444794
1445− if (config._dayOfYear > daysInYear(yearToUse)) {
1446− config._pf._overflowDayOfYear = true;
795+ function getIsLeapYear() {
796+ return isLeapYear(this.year());
797+ }
798+
799+ function makeGetSet(unit, keepTime) {
800+ return function (value) {
801+ if (value != null) {
802+ set$1(this, unit, value);
803+ hooks.updateOffset(this, keepTime);
804+ return this;
805+ } else {
806+ return get(this, unit);
1447807 }
808+ };
809+ }
1448810
1449− date = makeUTCDate(yearToUse, 0, config._dayOfYear);
1450− config._a[MONTH] = date.getUTCMonth();
1451− config._a[DATE] = date.getUTCDate();
811+ function get(mom, unit) {
812+ return mom.isValid() ?
813+ mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
814+ }
815+
816+ function set$1(mom, unit, value) {
817+ if (mom.isValid() && !isNaN(value)) {
818+ if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
819+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
820+ }
821+ else {
822+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
823+ }
1452824 }
825+ }
1453826
1454− // Default to current date.
1455− // * if no year, month, day of month are given, default to today
1456− // * if day of month is given, default month and year
1457− // * if month is given, default only year
1458− // * if year is given, don't default anything
1459− for (i = 0; i < 3 && config._a[i] == null; ++i) {
1460− config._a[i] = input[i] = currentDate[i];
1461− }
827+ // MOMENTS
1462828
1463− // Zero out whatever was not defaulted, including time
1464− for (; i < 7; i++) {
1465− config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1466− }
1467−
1468− // Check for 24:00:00.000
1469− if (config._a[HOUR] === 24 &&
1470− config._a[MINUTE] === 0 &&
1471− config._a[SECOND] === 0 &&
1472− config._a[MILLISECOND] === 0) {
1473− config._nextDay = true;
1474− config._a[HOUR] = 0;
829+ function stringGet(units) {
830+ units = normalizeUnits(units);
831+ if (isFunction(this[units])) {
832+ return this[units]();
1475833 }
834+ return this;
835+ }
1476836
1477− config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
1478− // Apply timezone offset from input. The actual utcOffset can be changed
1479− // with parseZone.
1480− if (config._tzm != null) {
1481− config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
1482− }
1483837
1484− if (config._nextDay) {
1485− config._a[HOUR] = 24;
838+ function stringSet(units, value) {
839+ if (typeof units === 'object') {
840+ units = normalizeObjectUnits(units);
841+ var prioritized = getPrioritizedUnits(units);
842+ for (var i = 0; i < prioritized.length; i++) {
843+ this[prioritized[i].unit](units[prioritized[i].unit]);
844+ }
845+ } else {
846+ units = normalizeUnits(units);
847+ if (isFunction(this[units])) {
848+ return this[units](value);
849+ }
1486850 }
851+ return this;
1487852 }
1488853
1489− function dateFromObject(config) {
1490− var normalizedInput;
1491−
1492− if (config._d) {
1493− return;
1494− }
854+ function mod(n, x) {
855+ return ((n % x) + x) % x;
856+ }
1495857
1496− normalizedInput = normalizeObjectUnits(config._i);
1497− config._a = [
1498− normalizedInput.year,
1499− normalizedInput.month,
1500− normalizedInput.day || normalizedInput.date,
1501− normalizedInput.hour,
1502− normalizedInput.minute,
1503− normalizedInput.second,
1504− normalizedInput.millisecond
1505− ];
858+ var indexOf;
1506859
1507− dateFromConfig(config);
860+ if (Array.prototype.indexOf) {
861+ indexOf = Array.prototype.indexOf;
862+ } else {
863+ indexOf = function (o) {
864+ // I know
865+ var i;
866+ for (i = 0; i < this.length; ++i) {
867+ if (this[i] === o) {
868+ return i;
869+ }
870+ }
871+ return -1;
872+ };
1508873 }
1509874
1510− function currentDateArray(config) {
1511− var now = new Date();
1512− if (config._useUTC) {
1513− return [
1514− now.getUTCFullYear(),
1515− now.getUTCMonth(),
1516− now.getUTCDate()
1517− ];
1518− } else {
1519− return [now.getFullYear(), now.getMonth(), now.getDate()];
875+ function daysInMonth(year, month) {
876+ if (isNaN(year) || isNaN(month)) {
877+ return NaN;
1520878 }
879+ var modMonth = mod(month, 12);
880+ year += (month - modMonth) / 12;
881+ return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
1521882 }
1522883
1523− // date from string and format string
1524− function makeDateFromStringAndFormat(config) {
1525− if (config._f === moment.ISO_8601) {
1526− parseISO(config);
1527− return;
1528− }
884+ // FORMATTING
1529885
1530− config._a = [];
1531− config._pf.empty = true;
886+ addFormatToken('M', ['MM', 2], 'Mo', function () {
887+ return this.month() + 1;
888+ });
1532889
1533− // This array is used to make a Date, either with `new Date` or `Date.UTC`
1534− var string = '' + config._i,
1535− i, parsedInput, tokens, token, skipped,
1536− stringLength = string.length,
1537− totalParsedInputLength = 0;
890+ addFormatToken('MMM', 0, 0, function (format) {
891+ return this.localeData().monthsShort(this, format);
892+ });
1538893
1539− tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
894+ addFormatToken('MMMM', 0, 0, function (format) {
895+ return this.localeData().months(this, format);
896+ });
1540897
1541− for (i = 0; i < tokens.length; i++) {
1542− token = tokens[i];
1543− parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
1544− if (parsedInput) {
1545− skipped = string.substr(0, string.indexOf(parsedInput));
1546− if (skipped.length > 0) {
1547− config._pf.unusedInput.push(skipped);
1548− }
1549− string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1550− totalParsedInputLength += parsedInput.length;
1551− }
1552− // don't parse if it's not a known token
1553− if (formatTokenFunctions[token]) {
1554− if (parsedInput) {
1555− config._pf.empty = false;
1556− }
1557− else {
1558− config._pf.unusedTokens.push(token);
1559− }
1560− addTimeToArrayFromToken(token, parsedInput, config);
1561− }
1562− else if (config._strict && !parsedInput) {
1563− config._pf.unusedTokens.push(token);
1564− }
1565− }
898+ // ALIASES
1566899
1567− // add remaining unparsed input length to the string
1568− config._pf.charsLeftOver = stringLength - totalParsedInputLength;
1569− if (string.length > 0) {
1570− config._pf.unusedInput.push(string);
900+ addUnitAlias('month', 'M');
901+
902+ // PRIORITY
903+
904+ addUnitPriority('month', 8);
905+
906+ // PARSING
907+
908+ addRegexToken('M', match1to2);
909+ addRegexToken('MM', match1to2, match2);
910+ addRegexToken('MMM', function (isStrict, locale) {
911+ return locale.monthsShortRegex(isStrict);
912+ });
913+ addRegexToken('MMMM', function (isStrict, locale) {
914+ return locale.monthsRegex(isStrict);
915+ });
916+
917+ addParseToken(['M', 'MM'], function (input, array) {
918+ array[MONTH] = toInt(input) - 1;
919+ });
920+
921+ addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
922+ var month = config._locale.monthsParse(input, token, config._strict);
923+ // if we didn't find a month name, mark the date as invalid.
924+ if (month != null) {
925+ array[MONTH] = month;
926+ } else {
927+ getParsingFlags(config).invalidMonth = input;
1571928 }
929+ });
1572930
1573− // clear _12h flag if hour is <= 12
1574− if (config._pf.bigHour === true && config._a[HOUR] <= 12) {
1575− config._pf.bigHour = undefined;
931+ // LOCALES
932+
933+ var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
934+ var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
935+ function localeMonths(m, format) {
936+ if (!m) {
937+ return isArray(this._months) ? this._months :
938+ this._months['standalone'];
1576939 }
1577− // handle meridiem
1578− config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR],
1579− config._meridiem);
1580− dateFromConfig(config);
1581− checkOverflow(config);
940+ return isArray(this._months) ? this._months[m.month()] :
941+ this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
1582942 }
1583943
1584− function unescapeFormat(s) {
1585− return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
1586− return p1 || p2 || p3 || p4;
1587− });
944+ var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
945+ function localeMonthsShort(m, format) {
946+ if (!m) {
947+ return isArray(this._monthsShort) ? this._monthsShort :
948+ this._monthsShort['standalone'];
949+ }
950+ return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
951+ this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
1588952 }
1589953
1590− // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1591− function regexpEscape(s) {
1592− return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
954+ function handleStrictParse(monthName, format, strict) {
955+ var i, ii, mom, llc = monthName.toLocaleLowerCase();
956+ if (!this._monthsParse) {
957+ // this is not used
958+ this._monthsParse = [];
959+ this._longMonthsParse = [];
960+ this._shortMonthsParse = [];
961+ for (i = 0; i < 12; ++i) {
962+ mom = createUTC([2000, i]);
963+ this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
964+ this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
965+ }
966+ }
967+
968+ if (strict) {
969+ if (format === 'MMM') {
970+ ii = indexOf.call(this._shortMonthsParse, llc);
971+ return ii !== -1 ? ii : null;
972+ } else {
973+ ii = indexOf.call(this._longMonthsParse, llc);
974+ return ii !== -1 ? ii : null;
975+ }
976+ } else {
977+ if (format === 'MMM') {
978+ ii = indexOf.call(this._shortMonthsParse, llc);
979+ if (ii !== -1) {
980+ return ii;
981+ }
982+ ii = indexOf.call(this._longMonthsParse, llc);
983+ return ii !== -1 ? ii : null;
984+ } else {
985+ ii = indexOf.call(this._longMonthsParse, llc);
986+ if (ii !== -1) {
987+ return ii;
988+ }
989+ ii = indexOf.call(this._shortMonthsParse, llc);
990+ return ii !== -1 ? ii : null;
991+ }
992+ }
1593993 }
1594994
1595− // date from string and array of format strings
1596− function makeDateFromStringAndArray(config) {
1597− var tempConfig,
1598− bestMoment,
995+ function localeMonthsParse(monthName, format, strict) {
996+ var i, mom, regex;
1599997
1600− scoreToBeat,
1601− i,
1602− currentScore;
998+ if (this._monthsParseExact) {
999+ return handleStrictParse.call(this, monthName, format, strict);
1000+ }
16031001
1604− if (config._f.length === 0) {
1605− config._pf.invalidFormat = true;
1606− config._d = new Date(NaN);
1607− return;
1002+ if (!this._monthsParse) {
1003+ this._monthsParse = [];
1004+ this._longMonthsParse = [];
1005+ this._shortMonthsParse = [];
16081006 }
16091007
1610− for (i = 0; i < config._f.length; i++) {
1611− currentScore = 0;
1612− tempConfig = copyConfig({}, config);
1613− if (config._useUTC != null) {
1614− tempConfig._useUTC = config._useUTC;
1008+ // TODO: add sorting
1009+ // Sorting makes sure if one month (or abbr) is a prefix of another
1010+ // see sorting in computeMonthsParse
1011+ for (i = 0; i < 12; i++) {
1012+ // make the regex if we don't have it already
1013+ mom = createUTC([2000, i]);
1014+ if (strict && !this._longMonthsParse[i]) {
1015+ this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
1016+ this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
16151017 }
1616− tempConfig._pf = defaultParsingFlags();
1617− tempConfig._f = config._f[i];
1618− makeDateFromStringAndFormat(tempConfig);
1619−
1620− if (!isValid(tempConfig)) {
1621− continue;
1018+ if (!strict && !this._monthsParse[i]) {
1019+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
1020+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
1021+ }
1022+ // test the regex
1023+ if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
1024+ return i;
1025+ } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
1026+ return i;
1027+ } else if (!strict && this._monthsParse[i].test(monthName)) {
1028+ return i;
16221029 }
1030+ }
1031+ }
16231032
1624− // if there is any input that was not parsed add a penalty for that format
1625− currentScore += tempConfig._pf.charsLeftOver;
1033+ // MOMENTS
16261034
1627− //or tokens
1628− currentScore += tempConfig._pf.unusedTokens.length * 10;
1035+ function setMonth(mom, value) {
1036+ var dayOfMonth;
16291037
1630− tempConfig._pf.score = currentScore;
1038+ if (!mom.isValid()) {
1039+ // No op
1040+ return mom;
1041+ }
16311042
1632− if (scoreToBeat == null || currentScore < scoreToBeat) {
1633− scoreToBeat = currentScore;
1634− bestMoment = tempConfig;
1043+ if (typeof value === 'string') {
1044+ if (/^\d+$/.test(value)) {
1045+ value = toInt(value);
1046+ } else {
1047+ value = mom.localeData().monthsParse(value);
1048+ // TODO: Another silent failure?
1049+ if (!isNumber(value)) {
1050+ return mom;
1051+ }
16351052 }
16361053 }
16371054
1638− extend(config, bestMoment || tempConfig);
1055+ dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
1056+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
1057+ return mom;
16391058 }
16401059
1641− // date from iso format
1642− function parseISO(config) {
1643− var i, l,
1644− string = config._i,
1645− match = isoRegex.exec(string);
1060+ function getSetMonth(value) {
1061+ if (value != null) {
1062+ setMonth(this, value);
1063+ hooks.updateOffset(this, true);
1064+ return this;
1065+ } else {
1066+ return get(this, 'Month');
1067+ }
1068+ }
16461069
1647− if (match) {
1648− config._pf.iso = true;
1649− for (i = 0, l = isoDates.length; i < l; i++) {
1650− if (isoDates[i][1].exec(string)) {
1651− // match[5] should be 'T' or undefined
1652− config._f = isoDates[i][0] + (match[6] || ' ');
1653− break;
1654− }
1655− }
1656− for (i = 0, l = isoTimes.length; i < l; i++) {
1657− if (isoTimes[i][1].exec(string)) {
1658− config._f += isoTimes[i][0];
1659− break;
1660− }
1070+ function getDaysInMonth() {
1071+ return daysInMonth(this.year(), this.month());
1072+ }
1073+
1074+ var defaultMonthsShortRegex = matchWord;
1075+ function monthsShortRegex(isStrict) {
1076+ if (this._monthsParseExact) {
1077+ if (!hasOwnProp(this, '_monthsRegex')) {
1078+ computeMonthsParse.call(this);
16611079 }
1662− if (string.match(parseTokenTimezone)) {
1663− config._f += 'Z';
1080+ if (isStrict) {
1081+ return this._monthsShortStrictRegex;
1082+ } else {
1083+ return this._monthsShortRegex;
16641084 }
1665− makeDateFromStringAndFormat(config);
16661085 } else {
1667− config._isValid = false;
1086+ if (!hasOwnProp(this, '_monthsShortRegex')) {
1087+ this._monthsShortRegex = defaultMonthsShortRegex;
1088+ }
1089+ return this._monthsShortStrictRegex && isStrict ?
1090+ this._monthsShortStrictRegex : this._monthsShortRegex;
16681091 }
16691092 }
16701093
1671− // date from iso format or fallback
1672− function makeDateFromString(config) {
1673− parseISO(config);
1674− if (config._isValid === false) {
1675− delete config._isValid;
1676− moment.createFromInputFallback(config);
1094+ var defaultMonthsRegex = matchWord;
1095+ function monthsRegex(isStrict) {
1096+ if (this._monthsParseExact) {
1097+ if (!hasOwnProp(this, '_monthsRegex')) {
1098+ computeMonthsParse.call(this);
1099+ }
1100+ if (isStrict) {
1101+ return this._monthsStrictRegex;
1102+ } else {
1103+ return this._monthsRegex;
1104+ }
1105+ } else {
1106+ if (!hasOwnProp(this, '_monthsRegex')) {
1107+ this._monthsRegex = defaultMonthsRegex;
1108+ }
1109+ return this._monthsStrictRegex && isStrict ?
1110+ this._monthsStrictRegex : this._monthsRegex;
16771111 }
16781112 }
16791113
1680− function map(arr, fn) {
1681− var res = [], i;
1682− for (i = 0; i < arr.length; ++i) {
1683− res.push(fn(arr[i], i));
1114+ function computeMonthsParse() {
1115+ function cmpLenRev(a, b) {
1116+ return b.length - a.length;
16841117 }
1685− return res;
1686− }
16871118
1688− function makeDateFromInput(config) {
1689− var input = config._i, matched;
1690− if (input === undefined) {
1691− config._d = new Date();
1692− } else if (isDate(input)) {
1693− config._d = new Date(+input);
1694− } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {
1695− config._d = new Date(+matched[1]);
1696− } else if (typeof input === 'string') {
1697− makeDateFromString(config);
1698− } else if (isArray(input)) {
1699− config._a = map(input.slice(0), function (obj) {
1700− return parseInt(obj, 10);
1701− });
1702− dateFromConfig(config);
1703− } else if (typeof(input) === 'object') {
1704− dateFromObject(config);
1705− } else if (typeof(input) === 'number') {
1706− // from milliseconds
1707− config._d = new Date(input);
1708− } else {
1709− moment.createFromInputFallback(config);
1119+ var shortPieces = [], longPieces = [], mixedPieces = [],
1120+ i, mom;
1121+ for (i = 0; i < 12; i++) {
1122+ // make the regex if we don't have it already
1123+ mom = createUTC([2000, i]);
1124+ shortPieces.push(this.monthsShort(mom, ''));
1125+ longPieces.push(this.months(mom, ''));
1126+ mixedPieces.push(this.months(mom, ''));
1127+ mixedPieces.push(this.monthsShort(mom, ''));
1128+ }
1129+ // Sorting makes sure if one month (or abbr) is a prefix of another it
1130+ // will match the longer piece.
1131+ shortPieces.sort(cmpLenRev);
1132+ longPieces.sort(cmpLenRev);
1133+ mixedPieces.sort(cmpLenRev);
1134+ for (i = 0; i < 12; i++) {
1135+ shortPieces[i] = regexEscape(shortPieces[i]);
1136+ longPieces[i] = regexEscape(longPieces[i]);
1137+ }
1138+ for (i = 0; i < 24; i++) {
1139+ mixedPieces[i] = regexEscape(mixedPieces[i]);
17101140 }
1141+
1142+ this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1143+ this._monthsShortRegex = this._monthsRegex;
1144+ this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1145+ this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
17111146 }
17121147
1713− function makeDate(y, m, d, h, M, s, ms) {
1714− //can't just apply() to create a date:
1715− //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1148+ function createDate(y, m, d, h, M, s, ms) {
1149+ // can't just apply() to create a date:
1150+ // https://stackoverflow.com/q/181348
17161151 var date = new Date(y, m, d, h, M, s, ms);
17171152
1718− //the date constructor doesn't accept years < 1970
1719− if (y < 1970) {
1153+ // the date constructor remaps years 0-99 to 1900-1999
1154+ if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
17201155 date.setFullYear(y);
17211156 }
17221157 return date;
17231158 }
17241159
1725− function makeUTCDate(y) {
1160+ function createUTCDate(y) {
17261161 var date = new Date(Date.UTC.apply(null, arguments));
1727− if (y < 1970) {
1162+
1163+ // the Date.UTC function remaps years 0-99 to 1900-1999
1164+ if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
17281165 date.setUTCFullYear(y);
17291166 }
17301167 return date;
17311168 }
17321169
1733− function parseWeekday(input, locale) {
1734− if (typeof input === 'string') {
1735− if (!isNaN(input)) {
1736− input = parseInt(input, 10);
1737− }
1738− else {
1739− input = locale.weekdaysParse(input);
1740− if (typeof input !== 'number') {
1741− return null;
1742− }
1743− }
1170+ // start-of-first-week - start-of-year
1171+ function firstWeekOffset(year, dow, doy) {
1172+ var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
1173+ fwd = 7 + dow - doy,
1174+ // first-week day local weekday -- which local weekday is fwd
1175+ fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
1176+
1177+ return -fwdlw + fwd - 1;
1178+ }
1179+
1180+ // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1181+ function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
1182+ var localWeekday = (7 + weekday - dow) % 7,
1183+ weekOffset = firstWeekOffset(year, dow, doy),
1184+ dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
1185+ resYear, resDayOfYear;
1186+
1187+ if (dayOfYear <= 0) {
1188+ resYear = year - 1;
1189+ resDayOfYear = daysInYear(resYear) + dayOfYear;
1190+ } else if (dayOfYear > daysInYear(year)) {
1191+ resYear = year + 1;
1192+ resDayOfYear = dayOfYear - daysInYear(year);
1193+ } else {
1194+ resYear = year;
1195+ resDayOfYear = dayOfYear;
17441196 }
1745− return input;
1197+
1198+ return {
1199+ year: resYear,
1200+ dayOfYear: resDayOfYear
1201+ };
17461202 }
17471203
1748− /************************************
1749− Relative Time
1750− ************************************/
1204+ function weekOfYear(mom, dow, doy) {
1205+ var weekOffset = firstWeekOffset(mom.year(), dow, doy),
1206+ week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
1207+ resWeek, resYear;
1208+
1209+ if (week < 1) {
1210+ resYear = mom.year() - 1;
1211+ resWeek = week + weeksInYear(resYear, dow, doy);
1212+ } else if (week > weeksInYear(mom.year(), dow, doy)) {
1213+ resWeek = week - weeksInYear(mom.year(), dow, doy);
1214+ resYear = mom.year() + 1;
1215+ } else {
1216+ resYear = mom.year();
1217+ resWeek = week;
1218+ }
17511219
1220+ return {
1221+ week: resWeek,
1222+ year: resYear
1223+ };
1224+ }
17521225
1753− // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
1754− function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
1755− return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
1226+ function weeksInYear(year, dow, doy) {
1227+ var weekOffset = firstWeekOffset(year, dow, doy),
1228+ weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
1229+ return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
17561230 }
17571231
1758− function relativeTime(posNegDuration, withoutSuffix, locale) {
1759− var duration = moment.duration(posNegDuration).abs(),
1760− seconds = round(duration.as('s')),
1761− minutes = round(duration.as('m')),
1762− hours = round(duration.as('h')),
1763− days = round(duration.as('d')),
1764− months = round(duration.as('M')),
1765− years = round(duration.as('y')),
1232+ // FORMATTING
17661233
1767− args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
1768− minutes === 1 && ['m'] ||
1769− minutes < relativeTimeThresholds.m && ['mm', minutes] ||
1770− hours === 1 && ['h'] ||
1771− hours < relativeTimeThresholds.h && ['hh', hours] ||
1772− days === 1 && ['d'] ||
1773− days < relativeTimeThresholds.d && ['dd', days] ||
1774− months === 1 && ['M'] ||
1775− months < relativeTimeThresholds.M && ['MM', months] ||
1776− years === 1 && ['y'] || ['yy', years];
1234+ addFormatToken('w', ['ww', 2], 'wo', 'week');
1235+ addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
17771236
1778− args[2] = withoutSuffix;
1779− args[3] = +posNegDuration > 0;
1780− args[4] = locale;
1781− return substituteTimeAgo.apply({}, args);
1782− }
1237+ // ALIASES
17831238
1239+ addUnitAlias('week', 'w');
1240+ addUnitAlias('isoWeek', 'W');
17841241
1785− /************************************
1786− Week of Year
1787− ************************************/
1242+ // PRIORITIES
17881243
1244+ addUnitPriority('week', 5);
1245+ addUnitPriority('isoWeek', 5);
17891246
1790− // firstDayOfWeek 0 = sun, 6 = sat
1791− // the day of the week that starts the week
1792− // (usually sunday or monday)
1793− // firstDayOfWeekOfYear 0 = sun, 6 = sat
1794− // the first week is the week that contains the first
1795− // of this day of the week
1796− // (eg. ISO weeks use thursday (4))
1797− function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
1798− var end = firstDayOfWeekOfYear - firstDayOfWeek,
1799− daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
1800− adjustedMoment;
1247+ // PARSING
18011248
1249+ addRegexToken('w', match1to2);
1250+ addRegexToken('ww', match1to2, match2);
1251+ addRegexToken('W', match1to2);
1252+ addRegexToken('WW', match1to2, match2);
18021253
1803− if (daysToDayOfWeek > end) {
1804− daysToDayOfWeek -= 7;
1805− }
1254+ addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
1255+ week[token.substr(0, 1)] = toInt(input);
1256+ });
18061257
1807− if (daysToDayOfWeek < end - 7) {
1808− daysToDayOfWeek += 7;
1809− }
1258+ // HELPERS
18101259
1811− adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');
1812− return {
1813− week: Math.ceil(adjustedMoment.dayOfYear() / 7),
1814− year: adjustedMoment.year()
1815− };
1260+ // LOCALES
1261+
1262+ function localeWeek(mom) {
1263+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
18161264 }
18171265
1818− //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1819− function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1820− var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
1266+ var defaultLocaleWeek = {
1267+ dow: 0, // Sunday is the first day of the week.
1268+ doy: 6 // The week that contains Jan 1st is the first week of the year.
1269+ };
18211270
1822− d = d === 0 ? 7 : d;
1823− weekday = weekday != null ? weekday : firstDayOfWeek;
1824− daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
1825− dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
1271+ function localeFirstDayOfWeek() {
1272+ return this._week.dow;
1273+ }
18261274
1827− return {
1828− year: dayOfYear > 0 ? year : year - 1,
1829− dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
1830− };
1275+ function localeFirstDayOfYear() {
1276+ return this._week.doy;
18311277 }
18321278
1833− /************************************
1834− Top Level Functions
1835− ************************************/
1279+ // MOMENTS
18361280
1837− function makeMoment(config) {
1838− var input = config._i,
1839− format = config._f,
1840− res;
1281+ function getSetWeek(input) {
1282+ var week = this.localeData().week(this);
1283+ return input == null ? week : this.add((input - week) * 7, 'd');
1284+ }
18411285
1842− config._locale = config._locale || moment.localeData(config._l);
1286+ function getSetISOWeek(input) {
1287+ var week = weekOfYear(this, 1, 4).week;
1288+ return input == null ? week : this.add((input - week) * 7, 'd');
1289+ }
18431290
1844− if (input === null || (format === undefined && input === '')) {
1845− return moment.invalid({nullInput: true});
1846− }
1291+ // FORMATTING
18471292
1848− if (typeof input === 'string') {
1849− config._i = input = config._locale.preparse(input);
1850− }
1293+ addFormatToken('d', 0, 'do', 'day');
18511294
1852− if (moment.isMoment(input)) {
1853− return new Moment(input, true);
1854− } else if (format) {
1855− if (isArray(format)) {
1856− makeDateFromStringAndArray(config);
1857− } else {
1858− makeDateFromStringAndFormat(config);
1859− }
1860− } else {
1861− makeDateFromInput(config);
1862− }
1295+ addFormatToken('dd', 0, 0, function (format) {
1296+ return this.localeData().weekdaysMin(this, format);
1297+ });
18631298
1864− res = new Moment(config);
1865− if (res._nextDay) {
1866− // Adding is smart enough around DST
1867− res.add(1, 'd');
1868− res._nextDay = undefined;
1869− }
1299+ addFormatToken('ddd', 0, 0, function (format) {
1300+ return this.localeData().weekdaysShort(this, format);
1301+ });
18701302
1871− return res;
1872− }
1303+ addFormatToken('dddd', 0, 0, function (format) {
1304+ return this.localeData().weekdays(this, format);
1305+ });
18731306
1874− moment = function (input, format, locale, strict) {
1875− var c;
1307+ addFormatToken('e', 0, 0, 'weekday');
1308+ addFormatToken('E', 0, 0, 'isoWeekday');
18761309
1877− if (typeof(locale) === 'boolean') {
1878− strict = locale;
1879− locale = undefined;
1310+ // ALIASES
1311+
1312+ addUnitAlias('day', 'd');
1313+ addUnitAlias('weekday', 'e');
1314+ addUnitAlias('isoWeekday', 'E');
1315+
1316+ // PRIORITY
1317+ addUnitPriority('day', 11);
1318+ addUnitPriority('weekday', 11);
1319+ addUnitPriority('isoWeekday', 11);
1320+
1321+ // PARSING
1322+
1323+ addRegexToken('d', match1to2);
1324+ addRegexToken('e', match1to2);
1325+ addRegexToken('E', match1to2);
1326+ addRegexToken('dd', function (isStrict, locale) {
1327+ return locale.weekdaysMinRegex(isStrict);
1328+ });
1329+ addRegexToken('ddd', function (isStrict, locale) {
1330+ return locale.weekdaysShortRegex(isStrict);
1331+ });
1332+ addRegexToken('dddd', function (isStrict, locale) {
1333+ return locale.weekdaysRegex(isStrict);
1334+ });
1335+
1336+ addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
1337+ var weekday = config._locale.weekdaysParse(input, token, config._strict);
1338+ // if we didn't get a weekday name, mark the date as invalid
1339+ if (weekday != null) {
1340+ week.d = weekday;
1341+ } else {
1342+ getParsingFlags(config).invalidWeekday = input;
18801343 }
1881− // object construction must be done this way.
1882− // https://github.com/moment/moment/issues/1423
1883− c = {};
1884− c._isAMomentObject = true;
1885− c._i = input;
1886− c._f = format;
1887− c._l = locale;
1888− c._strict = strict;
1889− c._isUTC = false;
1890− c._pf = defaultParsingFlags();
1344+ });
18911345
1892− return makeMoment(c);
1893− };
1346+ addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
1347+ week[token] = toInt(input);
1348+ });
18941349
1895− moment.suppressDeprecationWarnings = false;
1350+ // HELPERS
18961351
1897− moment.createFromInputFallback = deprecate(
1898− 'moment construction falls back to js Date. This is ' +
1899− 'discouraged and will be removed in upcoming major ' +
1900− 'release. Please refer to ' +
1901− 'https://github.com/moment/moment/issues/1407 for more info.',
1902− function (config) {
1903− config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
1352+ function parseWeekday(input, locale) {
1353+ if (typeof input !== 'string') {
1354+ return input;
19041355 }
1905− );
19061356
1907− // Pick a moment m from moments so that m[fn](other) is true for all
1908− // other. This relies on the function fn to be transitive.
1909− //
1910− // moments should either be an array of moment objects or an array, whose
1911− // first element is an array of moment objects.
1912− function pickBy(fn, moments) {
1913− var res, i;
1914− if (moments.length === 1 && isArray(moments[0])) {
1915− moments = moments[0];
1357+ if (!isNaN(input)) {
1358+ return parseInt(input, 10);
19161359 }
1917− if (!moments.length) {
1918− return moment();
1360+
1361+ input = locale.weekdaysParse(input);
1362+ if (typeof input === 'number') {
1363+ return input;
19191364 }
1920− res = moments[0];
1921− for (i = 1; i < moments.length; ++i) {
1922− if (moments[i][fn](res)) {
1923− res = moments[i];
1365+
1366+ return null;
1367+ }
1368+
1369+ function parseIsoWeekday(input, locale) {
1370+ if (typeof input === 'string') {
1371+ return locale.weekdaysParse(input) % 7 || 7;
1372+ }
1373+ return isNaN(input) ? null : input;
1374+ }
1375+
1376+ // LOCALES
1377+
1378+ var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
1379+ function localeWeekdays(m, format) {
1380+ if (!m) {
1381+ return isArray(this._weekdays) ? this._weekdays :
1382+ this._weekdays['standalone'];
1383+ }
1384+ return isArray(this._weekdays) ? this._weekdays[m.day()] :
1385+ this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
1386+ }
1387+
1388+ var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
1389+ function localeWeekdaysShort(m) {
1390+ return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
1391+ }
1392+
1393+ var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
1394+ function localeWeekdaysMin(m) {
1395+ return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
1396+ }
1397+
1398+ function handleStrictParse$1(weekdayName, format, strict) {
1399+ var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
1400+ if (!this._weekdaysParse) {
1401+ this._weekdaysParse = [];
1402+ this._shortWeekdaysParse = [];
1403+ this._minWeekdaysParse = [];
1404+
1405+ for (i = 0; i < 7; ++i) {
1406+ mom = createUTC([2000, 1]).day(i);
1407+ this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
1408+ this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
1409+ this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
1410+ }
1411+ }
1412+
1413+ if (strict) {
1414+ if (format === 'dddd') {
1415+ ii = indexOf.call(this._weekdaysParse, llc);
1416+ return ii !== -1 ? ii : null;
1417+ } else if (format === 'ddd') {
1418+ ii = indexOf.call(this._shortWeekdaysParse, llc);
1419+ return ii !== -1 ? ii : null;
1420+ } else {
1421+ ii = indexOf.call(this._minWeekdaysParse, llc);
1422+ return ii !== -1 ? ii : null;
1423+ }
1424+ } else {
1425+ if (format === 'dddd') {
1426+ ii = indexOf.call(this._weekdaysParse, llc);
1427+ if (ii !== -1) {
1428+ return ii;
1429+ }
1430+ ii = indexOf.call(this._shortWeekdaysParse, llc);
1431+ if (ii !== -1) {
1432+ return ii;
1433+ }
1434+ ii = indexOf.call(this._minWeekdaysParse, llc);
1435+ return ii !== -1 ? ii : null;
1436+ } else if (format === 'ddd') {
1437+ ii = indexOf.call(this._shortWeekdaysParse, llc);
1438+ if (ii !== -1) {
1439+ return ii;
1440+ }
1441+ ii = indexOf.call(this._weekdaysParse, llc);
1442+ if (ii !== -1) {
1443+ return ii;
1444+ }
1445+ ii = indexOf.call(this._minWeekdaysParse, llc);
1446+ return ii !== -1 ? ii : null;
1447+ } else {
1448+ ii = indexOf.call(this._minWeekdaysParse, llc);
1449+ if (ii !== -1) {
1450+ return ii;
1451+ }
1452+ ii = indexOf.call(this._weekdaysParse, llc);
1453+ if (ii !== -1) {
1454+ return ii;
1455+ }
1456+ ii = indexOf.call(this._shortWeekdaysParse, llc);
1457+ return ii !== -1 ? ii : null;
19241458 }
19251459 }
1926− return res;
19271460 }
19281461
1929− moment.min = function () {
1930− var args = [].slice.call(arguments, 0);
1462+ function localeWeekdaysParse(weekdayName, format, strict) {
1463+ var i, mom, regex;
19311464
1932− return pickBy('isBefore', args);
1933− };
1465+ if (this._weekdaysParseExact) {
1466+ return handleStrictParse$1.call(this, weekdayName, format, strict);
1467+ }
19341468
1935− moment.max = function () {
1936− var args = [].slice.call(arguments, 0);
1469+ if (!this._weekdaysParse) {
1470+ this._weekdaysParse = [];
1471+ this._minWeekdaysParse = [];
1472+ this._shortWeekdaysParse = [];
1473+ this._fullWeekdaysParse = [];
1474+ }
19371475
1938− return pickBy('isAfter', args);
1939− };
1476+ for (i = 0; i < 7; i++) {
1477+ // make the regex if we don't have it already
1478+
1479+ mom = createUTC([2000, 1]).day(i);
1480+ if (strict && !this._fullWeekdaysParse[i]) {
1481+ this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
1482+ this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
1483+ this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
1484+ }
1485+ if (!this._weekdaysParse[i]) {
1486+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
1487+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
1488+ }
1489+ // test the regex
1490+ if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
1491+ return i;
1492+ } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
1493+ return i;
1494+ } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
1495+ return i;
1496+ } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
1497+ return i;
1498+ }
1499+ }
1500+ }
19401501
1941− // creating with utc
1942− moment.utc = function (input, format, locale, strict) {
1943− var c;
1502+ // MOMENTS
19441503
1945− if (typeof(locale) === 'boolean') {
1946− strict = locale;
1947− locale = undefined;
1504+ function getSetDayOfWeek(input) {
1505+ if (!this.isValid()) {
1506+ return input != null ? this : NaN;
19481507 }
1949− // object construction must be done this way.
1950− // https://github.com/moment/moment/issues/1423
1951− c = {};
1952− c._isAMomentObject = true;
1953− c._useUTC = true;
1954− c._isUTC = true;
1955− c._l = locale;
1956− c._i = input;
1957− c._f = format;
1958− c._strict = strict;
1959− c._pf = defaultParsingFlags();
1508+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1509+ if (input != null) {
1510+ input = parseWeekday(input, this.localeData());
1511+ return this.add(input - day, 'd');
1512+ } else {
1513+ return day;
1514+ }
1515+ }
19601516
1961− return makeMoment(c).utc();
1962− };
1517+ function getSetLocaleDayOfWeek(input) {
1518+ if (!this.isValid()) {
1519+ return input != null ? this : NaN;
1520+ }
1521+ var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
1522+ return input == null ? weekday : this.add(input - weekday, 'd');
1523+ }
19631524
1964− // creating with unix timestamp (in seconds)
1965− moment.unix = function (input) {
1966− return moment(input * 1000);
1967− };
1525+ function getSetISODayOfWeek(input) {
1526+ if (!this.isValid()) {
1527+ return input != null ? this : NaN;
1528+ }
19681529
1969− // duration
1970− moment.duration = function (input, key) {
1971− var duration = input,
1972− // matching against regexp is expensive, do it on demand
1973− match = null,
1974− sign,
1975− ret,
1976− parseIso,
1977− diffRes;
1530+ // behaves the same as moment#day except
1531+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
1532+ // as a setter, sunday should belong to the previous week.
19781533
1979− if (moment.isDuration(input)) {
1980− duration = {
1981− ms: input._milliseconds,
1982− d: input._days,
1983− M: input._months
1984− };
1985− } else if (typeof input === 'number') {
1986− duration = {};
1987− if (key) {
1988− duration[key] = input;
1534+ if (input != null) {
1535+ var weekday = parseIsoWeekday(input, this.localeData());
1536+ return this.day(this.day() % 7 ? weekday : weekday - 7);
1537+ } else {
1538+ return this.day() || 7;
1539+ }
1540+ }
1541+
1542+ var defaultWeekdaysRegex = matchWord;
1543+ function weekdaysRegex(isStrict) {
1544+ if (this._weekdaysParseExact) {
1545+ if (!hasOwnProp(this, '_weekdaysRegex')) {
1546+ computeWeekdaysParse.call(this);
1547+ }
1548+ if (isStrict) {
1549+ return this._weekdaysStrictRegex;
19891550 } else {
1990− duration.milliseconds = input;
1551+ return this._weekdaysRegex;
19911552 }
1992− } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
1993− sign = (match[1] === '-') ? -1 : 1;
1994− duration = {
1995− y: 0,
1996− d: toInt(match[DATE]) * sign,
1997− h: toInt(match[HOUR]) * sign,
1998− m: toInt(match[MINUTE]) * sign,
1999− s: toInt(match[SECOND]) * sign,
2000− ms: toInt(match[MILLISECOND]) * sign
2001− };
2002− } else if (!!(match = isoDurationRegex.exec(input))) {
2003− sign = (match[1] === '-') ? -1 : 1;
2004− parseIso = function (inp) {
2005− // We'd normally use ~~inp for this, but unfortunately it also
2006− // converts floats to ints.
2007− // inp may be undefined, so careful calling replace on it.
2008− var res = inp && parseFloat(inp.replace(',', '.'));
2009− // apply sign while we're at it
2010− return (isNaN(res) ? 0 : res) * sign;
2011− };
2012− duration = {
2013− y: parseIso(match[2]),
2014− M: parseIso(match[3]),
2015− d: parseIso(match[4]),
2016− h: parseIso(match[5]),
2017− m: parseIso(match[6]),
2018− s: parseIso(match[7]),
2019− w: parseIso(match[8])
2020− };
2021− } else if (duration == null) {// checks for null or undefined
2022− duration = {};
2023− } else if (typeof duration === 'object' &&
2024− ('from' in duration || 'to' in duration)) {
2025− diffRes = momentsDifference(moment(duration.from), moment(duration.to));
1553+ } else {
1554+ if (!hasOwnProp(this, '_weekdaysRegex')) {
1555+ this._weekdaysRegex = defaultWeekdaysRegex;
1556+ }
1557+ return this._weekdaysStrictRegex && isStrict ?
1558+ this._weekdaysStrictRegex : this._weekdaysRegex;
1559+ }
1560+ }
20261561
2027− duration = {};
2028− duration.ms = diffRes.milliseconds;
2029− duration.M = diffRes.months;
1562+ var defaultWeekdaysShortRegex = matchWord;
1563+ function weekdaysShortRegex(isStrict) {
1564+ if (this._weekdaysParseExact) {
1565+ if (!hasOwnProp(this, '_weekdaysRegex')) {
1566+ computeWeekdaysParse.call(this);
1567+ }
1568+ if (isStrict) {
1569+ return this._weekdaysShortStrictRegex;
1570+ } else {
1571+ return this._weekdaysShortRegex;
1572+ }
1573+ } else {
1574+ if (!hasOwnProp(this, '_weekdaysShortRegex')) {
1575+ this._weekdaysShortRegex = defaultWeekdaysShortRegex;
1576+ }
1577+ return this._weekdaysShortStrictRegex && isStrict ?
1578+ this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
20301579 }
1580+ }
20311581
2032− ret = new Duration(duration);
1582+ var defaultWeekdaysMinRegex = matchWord;
1583+ function weekdaysMinRegex(isStrict) {
1584+ if (this._weekdaysParseExact) {
1585+ if (!hasOwnProp(this, '_weekdaysRegex')) {
1586+ computeWeekdaysParse.call(this);
1587+ }
1588+ if (isStrict) {
1589+ return this._weekdaysMinStrictRegex;
1590+ } else {
1591+ return this._weekdaysMinRegex;
1592+ }
1593+ } else {
1594+ if (!hasOwnProp(this, '_weekdaysMinRegex')) {
1595+ this._weekdaysMinRegex = defaultWeekdaysMinRegex;
1596+ }
1597+ return this._weekdaysMinStrictRegex && isStrict ?
1598+ this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
1599+ }
1600+ }
20331601
2034− if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {
2035− ret._locale = input._locale;
1602+
1603+ function computeWeekdaysParse() {
1604+ function cmpLenRev(a, b) {
1605+ return b.length - a.length;
20361606 }
20371607
2038− return ret;
2039− };
1608+ var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
1609+ i, mom, minp, shortp, longp;
1610+ for (i = 0; i < 7; i++) {
1611+ // make the regex if we don't have it already
1612+ mom = createUTC([2000, 1]).day(i);
1613+ minp = this.weekdaysMin(mom, '');
1614+ shortp = this.weekdaysShort(mom, '');
1615+ longp = this.weekdays(mom, '');
1616+ minPieces.push(minp);
1617+ shortPieces.push(shortp);
1618+ longPieces.push(longp);
1619+ mixedPieces.push(minp);
1620+ mixedPieces.push(shortp);
1621+ mixedPieces.push(longp);
1622+ }
1623+ // Sorting makes sure if one weekday (or abbr) is a prefix of another it
1624+ // will match the longer piece.
1625+ minPieces.sort(cmpLenRev);
1626+ shortPieces.sort(cmpLenRev);
1627+ longPieces.sort(cmpLenRev);
1628+ mixedPieces.sort(cmpLenRev);
1629+ for (i = 0; i < 7; i++) {
1630+ shortPieces[i] = regexEscape(shortPieces[i]);
1631+ longPieces[i] = regexEscape(longPieces[i]);
1632+ mixedPieces[i] = regexEscape(mixedPieces[i]);
1633+ }
20401634
2041− // version number
2042− moment.version = VERSION;
1635+ this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1636+ this._weekdaysShortRegex = this._weekdaysRegex;
1637+ this._weekdaysMinRegex = this._weekdaysRegex;
20431638
2044− // default format
2045− moment.defaultFormat = isoFormat;
1639+ this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1640+ this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
1641+ this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
1642+ }
20461643
2047− // constant that refers to the ISO standard
2048− moment.ISO_8601 = function () {};
1644+ // FORMATTING
20491645
2050− // Plugins that add properties should also add the key here (null value),
2051− // so we can properly clone ourselves.
2052− moment.momentProperties = momentProperties;
1646+ function hFormat() {
1647+ return this.hours() % 12 || 12;
1648+ }
20531649
2054− // This function will be called whenever a moment is mutated.
2055− // It is intended to keep the offset in sync with the timezone.
2056− moment.updateOffset = function () {};
1650+ function kFormat() {
1651+ return this.hours() || 24;
1652+ }
20571653
2058− // This function allows you to set a threshold for relative time strings
2059− moment.relativeTimeThreshold = function (threshold, limit) {
2060− if (relativeTimeThresholds[threshold] === undefined) {
2061− return false;
2062− }
2063− if (limit === undefined) {
2064− return relativeTimeThresholds[threshold];
1654+ addFormatToken('H', ['HH', 2], 0, 'hour');
1655+ addFormatToken('h', ['hh', 2], 0, hFormat);
1656+ addFormatToken('k', ['kk', 2], 0, kFormat);
1657+
1658+ addFormatToken('hmm', 0, 0, function () {
1659+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
1660+ });
1661+
1662+ addFormatToken('hmmss', 0, 0, function () {
1663+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
1664+ zeroFill(this.seconds(), 2);
1665+ });
1666+
1667+ addFormatToken('Hmm', 0, 0, function () {
1668+ return '' + this.hours() + zeroFill(this.minutes(), 2);
1669+ });
1670+
1671+ addFormatToken('Hmmss', 0, 0, function () {
1672+ return '' + this.hours() + zeroFill(this.minutes(), 2) +
1673+ zeroFill(this.seconds(), 2);
1674+ });
1675+
1676+ function meridiem(token, lowercase) {
1677+ addFormatToken(token, 0, 0, function () {
1678+ return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
1679+ });
1680+ }
1681+
1682+ meridiem('a', true);
1683+ meridiem('A', false);
1684+
1685+ // ALIASES
1686+
1687+ addUnitAlias('hour', 'h');
1688+
1689+ // PRIORITY
1690+ addUnitPriority('hour', 13);
1691+
1692+ // PARSING
1693+
1694+ function matchMeridiem(isStrict, locale) {
1695+ return locale._meridiemParse;
1696+ }
1697+
1698+ addRegexToken('a', matchMeridiem);
1699+ addRegexToken('A', matchMeridiem);
1700+ addRegexToken('H', match1to2);
1701+ addRegexToken('h', match1to2);
1702+ addRegexToken('k', match1to2);
1703+ addRegexToken('HH', match1to2, match2);
1704+ addRegexToken('hh', match1to2, match2);
1705+ addRegexToken('kk', match1to2, match2);
1706+
1707+ addRegexToken('hmm', match3to4);
1708+ addRegexToken('hmmss', match5to6);
1709+ addRegexToken('Hmm', match3to4);
1710+ addRegexToken('Hmmss', match5to6);
1711+
1712+ addParseToken(['H', 'HH'], HOUR);
1713+ addParseToken(['k', 'kk'], function (input, array, config) {
1714+ var kInput = toInt(input);
1715+ array[HOUR] = kInput === 24 ? 0 : kInput;
1716+ });
1717+ addParseToken(['a', 'A'], function (input, array, config) {
1718+ config._isPm = config._locale.isPM(input);
1719+ config._meridiem = input;
1720+ });
1721+ addParseToken(['h', 'hh'], function (input, array, config) {
1722+ array[HOUR] = toInt(input);
1723+ getParsingFlags(config).bigHour = true;
1724+ });
1725+ addParseToken('hmm', function (input, array, config) {
1726+ var pos = input.length - 2;
1727+ array[HOUR] = toInt(input.substr(0, pos));
1728+ array[MINUTE] = toInt(input.substr(pos));
1729+ getParsingFlags(config).bigHour = true;
1730+ });
1731+ addParseToken('hmmss', function (input, array, config) {
1732+ var pos1 = input.length - 4;
1733+ var pos2 = input.length - 2;
1734+ array[HOUR] = toInt(input.substr(0, pos1));
1735+ array[MINUTE] = toInt(input.substr(pos1, 2));
1736+ array[SECOND] = toInt(input.substr(pos2));
1737+ getParsingFlags(config).bigHour = true;
1738+ });
1739+ addParseToken('Hmm', function (input, array, config) {
1740+ var pos = input.length - 2;
1741+ array[HOUR] = toInt(input.substr(0, pos));
1742+ array[MINUTE] = toInt(input.substr(pos));
1743+ });
1744+ addParseToken('Hmmss', function (input, array, config) {
1745+ var pos1 = input.length - 4;
1746+ var pos2 = input.length - 2;
1747+ array[HOUR] = toInt(input.substr(0, pos1));
1748+ array[MINUTE] = toInt(input.substr(pos1, 2));
1749+ array[SECOND] = toInt(input.substr(pos2));
1750+ });
1751+
1752+ // LOCALES
1753+
1754+ function localeIsPM(input) {
1755+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
1756+ // Using charAt should be more compatible.
1757+ return ((input + '').toLowerCase().charAt(0) === 'p');
1758+ }
1759+
1760+ var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
1761+ function localeMeridiem(hours, minutes, isLower) {
1762+ if (hours > 11) {
1763+ return isLower ? 'pm' : 'PM';
1764+ } else {
1765+ return isLower ? 'am' : 'AM';
20651766 }
2066− relativeTimeThresholds[threshold] = limit;
2067− return true;
1767+ }
1768+
1769+
1770+ // MOMENTS
1771+
1772+ // Setting the hour should keep the time, because the user explicitly
1773+ // specified which hour he wants. So trying to maintain the same hour (in
1774+ // a new timezone) makes sense. Adding/subtracting hours does not follow
1775+ // this rule.
1776+ var getSetHour = makeGetSet('Hours', true);
1777+
1778+ // months
1779+ // week
1780+ // weekdays
1781+ // meridiem
1782+ var baseConfig = {
1783+ calendar: defaultCalendar,
1784+ longDateFormat: defaultLongDateFormat,
1785+ invalidDate: defaultInvalidDate,
1786+ ordinal: defaultOrdinal,
1787+ dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
1788+ relativeTime: defaultRelativeTime,
1789+
1790+ months: defaultLocaleMonths,
1791+ monthsShort: defaultLocaleMonthsShort,
1792+
1793+ week: defaultLocaleWeek,
1794+
1795+ weekdays: defaultLocaleWeekdays,
1796+ weekdaysMin: defaultLocaleWeekdaysMin,
1797+ weekdaysShort: defaultLocaleWeekdaysShort,
1798+
1799+ meridiemParse: defaultLocaleMeridiemParse
20681800 };
20691801
2070− moment.lang = deprecate(
2071− 'moment.lang is deprecated. Use moment.locale instead.',
2072− function (key, value) {
2073− return moment.locale(key, value);
1802+ // internal storage for locale config files
1803+ var locales = {};
1804+ var localeFamilies = {};
1805+ var globalLocale;
1806+
1807+ function normalizeLocale(key) {
1808+ return key ? key.toLowerCase().replace('_', '-') : key;
1809+ }
1810+
1811+ // pick the locale from the array
1812+ // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
1813+ // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
1814+ function chooseLocale(names) {
1815+ var i = 0, j, next, locale, split;
1816+
1817+ while (i < names.length) {
1818+ split = normalizeLocale(names[i]).split('-');
1819+ j = split.length;
1820+ next = normalizeLocale(names[i + 1]);
1821+ next = next ? next.split('-') : null;
1822+ while (j > 0) {
1823+ locale = loadLocale(split.slice(0, j).join('-'));
1824+ if (locale) {
1825+ return locale;
1826+ }
1827+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
1828+ //the next array item is better than a shallower substring of this one
1829+ break;
1830+ }
1831+ j--;
1832+ }
1833+ i++;
1834+ }
1835+ return null;
1836+ }
1837+
1838+ function loadLocale(name) {
1839+ var oldLocale = null;
1840+ // TODO: Find a better way to register and load all the locales in Node
1841+ if (!locales[name] && (typeof module !== 'undefined') &&
1842+ module && module.exports) {
1843+ try {
1844+ oldLocale = globalLocale._abbr;
1845+ var aliasedRequire = require;
1846+ aliasedRequire('./locale/' + name);
1847+ getSetGlobalLocale(oldLocale);
1848+ } catch (e) { }
20741849 }
2075− );
1850+ return locales[name];
1851+ }
20761852
20771853 // This function will load locale and then set the global locale. If
20781854 // no arguments are passed in, it will simply return the current global
20791855 // locale key.
2080− moment.locale = function (key, values) {
1856+ function getSetGlobalLocale(key, values) {
20811857 var data;
20821858 if (key) {
2083− if (typeof(values) !== 'undefined') {
2084− data = moment.defineLocale(key, values);
1859+ if (isUndefined(values)) {
1860+ data = getLocale(key);
20851861 }
20861862 else {
2087− data = moment.localeData(key);
1863+ data = defineLocale(key, values);
20881864 }
20891865
20901866 if (data) {
2091− moment.duration._locale = moment._locale = data;
1867+ // moment.duration._locale = moment._locale = data;
1868+ globalLocale = data;
20921869 }
20931870 }
20941871
2095− return moment._locale._abbr;
2096− };
2097−
2098− moment.defineLocale = function (name, values) {
2099− if (values !== null) {
2100− values.abbr = name;
2101− if (!locales[name]) {
2102− locales[name] = new Locale();
2103− }
2104− locales[name].set(values);
1872+ return globalLocale._abbr;
1873+ }
1874+
1875+ function defineLocale(name, config) {
1876+ if (config !== null) {
1877+ var parentConfig = baseConfig;
1878+ config.abbr = name;
1879+ if (locales[name] != null) {
1880+ deprecateSimple('defineLocaleOverride',
1881+ 'use moment.updateLocale(localeName, config) to change ' +
1882+ 'an existing locale. moment.defineLocale(localeName, ' +
1883+ 'config) should only be used for creating a new locale ' +
1884+ 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
1885+ parentConfig = locales[name]._config;
1886+ } else if (config.parentLocale != null) {
1887+ if (locales[config.parentLocale] != null) {
1888+ parentConfig = locales[config.parentLocale]._config;
1889+ } else {
1890+ if (!localeFamilies[config.parentLocale]) {
1891+ localeFamilies[config.parentLocale] = [];
1892+ }
1893+ localeFamilies[config.parentLocale].push({
1894+ name: name,
1895+ config: config
1896+ });
1897+ return null;
1898+ }
1899+ }
1900+ locales[name] = new Locale(mergeConfigs(parentConfig, config));
1901+
1902+ if (localeFamilies[name]) {
1903+ localeFamilies[name].forEach(function (x) {
1904+ defineLocale(x.name, x.config);
1905+ });
1906+ }
1907+
1908+ // backwards compat for now: also set the locale
1909+ // make sure we set the locale AFTER all child locales have been
1910+ // created, so we won't end up with the child locale set.
1911+ getSetGlobalLocale(name);
21051912
2106− // backwards compat for now: also set the locale
2107− moment.locale(name);
21081913
21091914 return locales[name];
21101915 } else {
@@ -2112,17 +1917,38 @@ · 1 unmodified line
21121917 delete locales[name];
21131918 return null;
21141919 }
2115− };
1920+ }
21161921
2117− moment.langData = deprecate(
2118− 'moment.langData is deprecated. Use moment.localeData instead.',
2119− function (key) {
2120− return moment.localeData(key);
1922+ function updateLocale(name, config) {
1923+ if (config != null) {
1924+ var locale, tmpLocale, parentConfig = baseConfig;
1925+ // MERGE
1926+ tmpLocale = loadLocale(name);
1927+ if (tmpLocale != null) {
1928+ parentConfig = tmpLocale._config;
1929+ }
1930+ config = mergeConfigs(parentConfig, config);
1931+ locale = new Locale(config);
1932+ locale.parentLocale = locales[name];
1933+ locales[name] = locale;
1934+
1935+ // backwards compat for now: also set the locale
1936+ getSetGlobalLocale(name);
1937+ } else {
1938+ // pass null for config to unupdate, useful for tests
1939+ if (locales[name] != null) {
1940+ if (locales[name].parentLocale != null) {
1941+ locales[name] = locales[name].parentLocale;
1942+ } else if (locales[name] != null) {
1943+ delete locales[name];
1944+ }
1945+ }
21211946 }
2122− );
1947+ return locales[name];
1948+ }
21231949
21241950 // returns locale data
2125− moment.localeData = function (key) {
1951+ function getLocale(key) {
21261952 var locale;
21271953
21281954 if (key && key._locale && key._locale._abbr) {
@@ -2130,7 +1956,7 @@ · 1 unmodified line
21301956 }
21311957
21321958 if (!key) {
2133− return moment._locale;
1959+ return globalLocale;
21341960 }
21351961
21361962 if (!isArray(key)) {
@@ -2143,901 +1969,2568 @@ · 6 unmodified lines
21431969 }
21441970
21451971 return chooseLocale(key);
1972+ }
1973+
1974+ function listLocales() {
1975+ return keys(locales);
1976+ }
1977+
1978+ function checkOverflow(m) {
1979+ var overflow;
1980+ var a = m._a;
1981+
1982+ if (a && getParsingFlags(m).overflow === -2) {
1983+ overflow =
1984+ a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
1985+ a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
1986+ a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
1987+ a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
1988+ a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
1989+ a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
1990+ -1;
1991+
1992+ if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
1993+ overflow = DATE;
1994+ }
1995+ if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
1996+ overflow = WEEK;
1997+ }
1998+ if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
1999+ overflow = WEEKDAY;
2000+ }
2001+
2002+ getParsingFlags(m).overflow = overflow;
2003+ }
2004+
2005+ return m;
2006+ }
2007+
2008+ // Pick the first defined of two or three arguments.
2009+ function defaults(a, b, c) {
2010+ if (a != null) {
2011+ return a;
2012+ }
2013+ if (b != null) {
2014+ return b;
2015+ }
2016+ return c;
2017+ }
2018+
2019+ function currentDateArray(config) {
2020+ // hooks is actually the exported moment object
2021+ var nowValue = new Date(hooks.now());
2022+ if (config._useUTC) {
2023+ return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
2024+ }
2025+ return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
2026+ }
2027+
2028+ // convert an array to a date.
2029+ // the array should mirror the parameters below
2030+ // note: all values past the year are optional and will default to the lowest possible value.
2031+ // [year, month, day , hour, minute, second, millisecond]
2032+ function configFromArray(config) {
2033+ var i, date, input = [], currentDate, expectedWeekday, yearToUse;
2034+
2035+ if (config._d) {
2036+ return;
2037+ }
2038+
2039+ currentDate = currentDateArray(config);
2040+
2041+ //compute day of the year from weeks and weekdays
2042+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
2043+ dayOfYearFromWeekInfo(config);
2044+ }
2045+
2046+ //if the day of the year is set, figure out what it is
2047+ if (config._dayOfYear != null) {
2048+ yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
2049+
2050+ if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
2051+ getParsingFlags(config)._overflowDayOfYear = true;
2052+ }
2053+
2054+ date = createUTCDate(yearToUse, 0, config._dayOfYear);
2055+ config._a[MONTH] = date.getUTCMonth();
2056+ config._a[DATE] = date.getUTCDate();
2057+ }
2058+
2059+ // Default to current date.
2060+ // * if no year, month, day of month are given, default to today
2061+ // * if day of month is given, default month and year
2062+ // * if month is given, default only year
2063+ // * if year is given, don't default anything
2064+ for (i = 0; i < 3 && config._a[i] == null; ++i) {
2065+ config._a[i] = input[i] = currentDate[i];
2066+ }
2067+
2068+ // Zero out whatever was not defaulted, including time
2069+ for (; i < 7; i++) {
2070+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
2071+ }
2072+
2073+ // Check for 24:00:00.000
2074+ if (config._a[HOUR] === 24 &&
2075+ config._a[MINUTE] === 0 &&
2076+ config._a[SECOND] === 0 &&
2077+ config._a[MILLISECOND] === 0) {
2078+ config._nextDay = true;
2079+ config._a[HOUR] = 0;
2080+ }
2081+
2082+ config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
2083+ expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
2084+
2085+ // Apply timezone offset from input. The actual utcOffset can be changed
2086+ // with parseZone.
2087+ if (config._tzm != null) {
2088+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
2089+ }
2090+
2091+ if (config._nextDay) {
2092+ config._a[HOUR] = 24;
2093+ }
2094+
2095+ // check for mismatching day of week
2096+ if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
2097+ getParsingFlags(config).weekdayMismatch = true;
2098+ }
2099+ }
2100+
2101+ function dayOfYearFromWeekInfo(config) {
2102+ var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
2103+
2104+ w = config._w;
2105+ if (w.GG != null || w.W != null || w.E != null) {
2106+ dow = 1;
2107+ doy = 4;
2108+
2109+ // TODO: We need to take the current isoWeekYear, but that depends on
2110+ // how we interpret now (local, utc, fixed offset). So create
2111+ // a now version of current config (take local/utc/offset flags, and
2112+ // create now).
2113+ weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
2114+ week = defaults(w.W, 1);
2115+ weekday = defaults(w.E, 1);
2116+ if (weekday < 1 || weekday > 7) {
2117+ weekdayOverflow = true;
2118+ }
2119+ } else {
2120+ dow = config._locale._week.dow;
2121+ doy = config._locale._week.doy;
2122+
2123+ var curWeek = weekOfYear(createLocal(), dow, doy);
2124+
2125+ weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
2126+
2127+ // Default to current week.
2128+ week = defaults(w.w, curWeek.week);
2129+
2130+ if (w.d != null) {
2131+ // weekday -- low day numbers are considered next week
2132+ weekday = w.d;
2133+ if (weekday < 0 || weekday > 6) {
2134+ weekdayOverflow = true;
2135+ }
2136+ } else if (w.e != null) {
2137+ // local weekday -- counting starts from begining of week
2138+ weekday = w.e + dow;
2139+ if (w.e < 0 || w.e > 6) {
2140+ weekdayOverflow = true;
2141+ }
2142+ } else {
2143+ // default to begining of week
2144+ weekday = dow;
2145+ }
2146+ }
2147+ if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
2148+ getParsingFlags(config)._overflowWeeks = true;
2149+ } else if (weekdayOverflow != null) {
2150+ getParsingFlags(config)._overflowWeekday = true;
2151+ } else {
2152+ temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
2153+ config._a[YEAR] = temp.year;
2154+ config._dayOfYear = temp.dayOfYear;
2155+ }
2156+ }
2157+
2158+ // iso 8601 regex
2159+ // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
2160+ var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
2161+ var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
2162+
2163+ var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
2164+
2165+ var isoDates = [
2166+ ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
2167+ ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
2168+ ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
2169+ ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
2170+ ['YYYY-DDD', /\d{4}-\d{3}/],
2171+ ['YYYY-MM', /\d{4}-\d\d/, false],
2172+ ['YYYYYYMMDD', /[+-]\d{10}/],
2173+ ['YYYYMMDD', /\d{8}/],
2174+ // YYYYMM is NOT allowed by the standard
2175+ ['GGGG[W]WWE', /\d{4}W\d{3}/],
2176+ ['GGGG[W]WW', /\d{4}W\d{2}/, false],
2177+ ['YYYYDDD', /\d{7}/]
2178+ ];
2179+
2180+ // iso time formats and regexes
2181+ var isoTimes = [
2182+ ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
2183+ ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
2184+ ['HH:mm:ss', /\d\d:\d\d:\d\d/],
2185+ ['HH:mm', /\d\d:\d\d/],
2186+ ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
2187+ ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
2188+ ['HHmmss', /\d\d\d\d\d\d/],
2189+ ['HHmm', /\d\d\d\d/],
2190+ ['HH', /\d\d/]
2191+ ];
2192+
2193+ var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
2194+
2195+ // date from iso format
2196+ function configFromISO(config) {
2197+ var i, l,
2198+ string = config._i,
2199+ match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
2200+ allowTime, dateFormat, timeFormat, tzFormat;
2201+
2202+ if (match) {
2203+ getParsingFlags(config).iso = true;
2204+
2205+ for (i = 0, l = isoDates.length; i < l; i++) {
2206+ if (isoDates[i][1].exec(match[1])) {
2207+ dateFormat = isoDates[i][0];
2208+ allowTime = isoDates[i][2] !== false;
2209+ break;
2210+ }
2211+ }
2212+ if (dateFormat == null) {
2213+ config._isValid = false;
2214+ return;
2215+ }
2216+ if (match[3]) {
2217+ for (i = 0, l = isoTimes.length; i < l; i++) {
2218+ if (isoTimes[i][1].exec(match[3])) {
2219+ // match[2] should be 'T' or space
2220+ timeFormat = (match[2] || ' ') + isoTimes[i][0];
2221+ break;
2222+ }
2223+ }
2224+ if (timeFormat == null) {
2225+ config._isValid = false;
2226+ return;
2227+ }
2228+ }
2229+ if (!allowTime && timeFormat != null) {
2230+ config._isValid = false;
2231+ return;
2232+ }
2233+ if (match[4]) {
2234+ if (tzRegex.exec(match[4])) {
2235+ tzFormat = 'Z';
2236+ } else {
2237+ config._isValid = false;
2238+ return;
2239+ }
2240+ }
2241+ config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
2242+ configFromStringAndFormat(config);
2243+ } else {
2244+ config._isValid = false;
2245+ }
2246+ }
2247+
2248+ // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
2249+ var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
2250+
2251+ function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
2252+ var result = [
2253+ untruncateYear(yearStr),
2254+ defaultLocaleMonthsShort.indexOf(monthStr),
2255+ parseInt(dayStr, 10),
2256+ parseInt(hourStr, 10),
2257+ parseInt(minuteStr, 10)
2258+ ];
2259+
2260+ if (secondStr) {
2261+ result.push(parseInt(secondStr, 10));
2262+ }
2263+
2264+ return result;
2265+ }
2266+
2267+ function untruncateYear(yearStr) {
2268+ var year = parseInt(yearStr, 10);
2269+ if (year <= 49) {
2270+ return 2000 + year;
2271+ } else if (year <= 999) {
2272+ return 1900 + year;
2273+ }
2274+ return year;
2275+ }
2276+
2277+ function preprocessRFC2822(s) {
2278+ // Remove comments and folding whitespace and replace multiple-spaces with a single space
2279+ return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').trim();
2280+ }
2281+
2282+ function checkWeekday(weekdayStr, parsedInput, config) {
2283+ if (weekdayStr) {
2284+ // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
2285+ var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
2286+ weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
2287+ if (weekdayProvided !== weekdayActual) {
2288+ getParsingFlags(config).weekdayMismatch = true;
2289+ config._isValid = false;
2290+ return false;
2291+ }
2292+ }
2293+ return true;
2294+ }
2295+
2296+ var obsOffsets = {
2297+ UT: 0,
2298+ GMT: 0,
2299+ EDT: -4 * 60,
2300+ EST: -5 * 60,
2301+ CDT: -5 * 60,
2302+ CST: -6 * 60,
2303+ MDT: -6 * 60,
2304+ MST: -7 * 60,
2305+ PDT: -7 * 60,
2306+ PST: -8 * 60
21462307 };
21472308
2148− // compare moment object
2149− moment.isMoment = function (obj) {
2150− return obj instanceof Moment ||
2151− (obj != null && hasOwnProp(obj, '_isAMomentObject'));
2152− };
2309+ function calculateOffset(obsOffset, militaryOffset, numOffset) {
2310+ if (obsOffset) {
2311+ return obsOffsets[obsOffset];
2312+ } else if (militaryOffset) {
2313+ // the only allowed military tz is Z
2314+ return 0;
2315+ } else {
2316+ var hm = parseInt(numOffset, 10);
2317+ var m = hm % 100, h = (hm - m) / 100;
2318+ return h * 60 + m;
2319+ }
2320+ }
2321+
2322+ // date and time from ref 2822 format
2323+ function configFromRFC2822(config) {
2324+ var match = rfc2822.exec(preprocessRFC2822(config._i));
2325+ if (match) {
2326+ var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
2327+ if (!checkWeekday(match[1], parsedArray, config)) {
2328+ return;
2329+ }
2330+
2331+ config._a = parsedArray;
2332+ config._tzm = calculateOffset(match[8], match[9], match[10]);
2333+
2334+ config._d = createUTCDate.apply(null, config._a);
2335+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
2336+
2337+ getParsingFlags(config).rfc2822 = true;
2338+ } else {
2339+ config._isValid = false;
2340+ }
2341+ }
2342+
2343+ // date from iso format or fallback
2344+ function configFromString(config) {
2345+ var matched = aspNetJsonRegex.exec(config._i);
2346+
2347+ if (matched !== null) {
2348+ config._d = new Date(+matched[1]);
2349+ return;
2350+ }
2351+
2352+ configFromISO(config);
2353+ if (config._isValid === false) {
2354+ delete config._isValid;
2355+ } else {
2356+ return;
2357+ }
2358+
2359+ configFromRFC2822(config);
2360+ if (config._isValid === false) {
2361+ delete config._isValid;
2362+ } else {
2363+ return;
2364+ }
2365+
2366+ // Final attempt, use Input Fallback
2367+ hooks.createFromInputFallback(config);
2368+ }
2369+
2370+ hooks.createFromInputFallback = deprecate(
2371+ 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
2372+ 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
2373+ 'discouraged and will be removed in an upcoming major release. Please refer to ' +
2374+ 'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
2375+ function (config) {
2376+ config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
2377+ }
2378+ );
2379+
2380+ // constant that refers to the ISO standard
2381+ hooks.ISO_8601 = function () { };
2382+
2383+ // constant that refers to the RFC 2822 form
2384+ hooks.RFC_2822 = function () { };
2385+
2386+ // date from string and format string
2387+ function configFromStringAndFormat(config) {
2388+ // TODO: Move this to another part of the creation flow to prevent circular deps
2389+ if (config._f === hooks.ISO_8601) {
2390+ configFromISO(config);
2391+ return;
2392+ }
2393+ if (config._f === hooks.RFC_2822) {
2394+ configFromRFC2822(config);
2395+ return;
2396+ }
2397+ config._a = [];
2398+ getParsingFlags(config).empty = true;
2399+
2400+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
2401+ var string = '' + config._i,
2402+ i, parsedInput, tokens, token, skipped,
2403+ stringLength = string.length,
2404+ totalParsedInputLength = 0;
2405+
2406+ tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
2407+
2408+ for (i = 0; i < tokens.length; i++) {
2409+ token = tokens[i];
2410+ parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
2411+ // console.log('token', token, 'parsedInput', parsedInput,
2412+ // 'regex', getParseRegexForToken(token, config));
2413+ if (parsedInput) {
2414+ skipped = string.substr(0, string.indexOf(parsedInput));
2415+ if (skipped.length > 0) {
2416+ getParsingFlags(config).unusedInput.push(skipped);
2417+ }
2418+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
2419+ totalParsedInputLength += parsedInput.length;
2420+ }
2421+ // don't parse if it's not a known token
2422+ if (formatTokenFunctions[token]) {
2423+ if (parsedInput) {
2424+ getParsingFlags(config).empty = false;
2425+ }
2426+ else {
2427+ getParsingFlags(config).unusedTokens.push(token);
2428+ }
2429+ addTimeToArrayFromToken(token, parsedInput, config);
2430+ }
2431+ else if (config._strict && !parsedInput) {
2432+ getParsingFlags(config).unusedTokens.push(token);
2433+ }
2434+ }
2435+
2436+ // add remaining unparsed input length to the string
2437+ getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
2438+ if (string.length > 0) {
2439+ getParsingFlags(config).unusedInput.push(string);
2440+ }
2441+
2442+ // clear _12h flag if hour is <= 12
2443+ if (config._a[HOUR] <= 12 &&
2444+ getParsingFlags(config).bigHour === true &&
2445+ config._a[HOUR] > 0) {
2446+ getParsingFlags(config).bigHour = undefined;
2447+ }
2448+
2449+ getParsingFlags(config).parsedDateParts = config._a.slice(0);
2450+ getParsingFlags(config).meridiem = config._meridiem;
2451+ // handle meridiem
2452+ config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
2453+
2454+ configFromArray(config);
2455+ checkOverflow(config);
2456+ }
2457+
2458+
2459+ function meridiemFixWrap(locale, hour, meridiem) {
2460+ var isPm;
2461+
2462+ if (meridiem == null) {
2463+ // nothing to do
2464+ return hour;
2465+ }
2466+ if (locale.meridiemHour != null) {
2467+ return locale.meridiemHour(hour, meridiem);
2468+ } else if (locale.isPM != null) {
2469+ // Fallback
2470+ isPm = locale.isPM(meridiem);
2471+ if (isPm && hour < 12) {
2472+ hour += 12;
2473+ }
2474+ if (!isPm && hour === 12) {
2475+ hour = 0;
2476+ }
2477+ return hour;
2478+ } else {
2479+ // this is not supposed to happen
2480+ return hour;
2481+ }
2482+ }
2483+
2484+ // date from string and array of format strings
2485+ function configFromStringAndArray(config) {
2486+ var tempConfig,
2487+ bestMoment,
2488+
2489+ scoreToBeat,
2490+ i,
2491+ currentScore;
2492+
2493+ if (config._f.length === 0) {
2494+ getParsingFlags(config).invalidFormat = true;
2495+ config._d = new Date(NaN);
2496+ return;
2497+ }
2498+
2499+ for (i = 0; i < config._f.length; i++) {
2500+ currentScore = 0;
2501+ tempConfig = copyConfig({}, config);
2502+ if (config._useUTC != null) {
2503+ tempConfig._useUTC = config._useUTC;
2504+ }
2505+ tempConfig._f = config._f[i];
2506+ configFromStringAndFormat(tempConfig);
2507+
2508+ if (!isValid(tempConfig)) {
2509+ continue;
2510+ }
2511+
2512+ // if there is any input that was not parsed add a penalty for that format
2513+ currentScore += getParsingFlags(tempConfig).charsLeftOver;
2514+
2515+ //or tokens
2516+ currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
2517+
2518+ getParsingFlags(tempConfig).score = currentScore;
2519+
2520+ if (scoreToBeat == null || currentScore < scoreToBeat) {
2521+ scoreToBeat = currentScore;
2522+ bestMoment = tempConfig;
2523+ }
2524+ }
2525+
2526+ extend(config, bestMoment || tempConfig);
2527+ }
2528+
2529+ function configFromObject(config) {
2530+ if (config._d) {
2531+ return;
2532+ }
2533+
2534+ var i = normalizeObjectUnits(config._i);
2535+ config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
2536+ return obj && parseInt(obj, 10);
2537+ });
2538+
2539+ configFromArray(config);
2540+ }
2541+
2542+ function createFromConfig(config) {
2543+ var res = new Moment(checkOverflow(prepareConfig(config)));
2544+ if (res._nextDay) {
2545+ // Adding is smart enough around DST
2546+ res.add(1, 'd');
2547+ res._nextDay = undefined;
2548+ }
2549+
2550+ return res;
2551+ }
2552+
2553+ function prepareConfig(config) {
2554+ var input = config._i,
2555+ format = config._f;
2556+
2557+ config._locale = config._locale || getLocale(config._l);
2558+
2559+ if (input === null || (format === undefined && input === '')) {
2560+ return createInvalid({ nullInput: true });
2561+ }
2562+
2563+ if (typeof input === 'string') {
2564+ config._i = input = config._locale.preparse(input);
2565+ }
2566+
2567+ if (isMoment(input)) {
2568+ return new Moment(checkOverflow(input));
2569+ } else if (isDate(input)) {
2570+ config._d = input;
2571+ } else if (isArray(format)) {
2572+ configFromStringAndArray(config);
2573+ } else if (format) {
2574+ configFromStringAndFormat(config);
2575+ } else {
2576+ configFromInput(config);
2577+ }
2578+
2579+ if (!isValid(config)) {
2580+ config._d = null;
2581+ }
2582+
2583+ return config;
2584+ }
2585+
2586+ function configFromInput(config) {
2587+ var input = config._i;
2588+ if (isUndefined(input)) {
2589+ config._d = new Date(hooks.now());
2590+ } else if (isDate(input)) {
2591+ config._d = new Date(input.valueOf());
2592+ } else if (typeof input === 'string') {
2593+ configFromString(config);
2594+ } else if (isArray(input)) {
2595+ config._a = map(input.slice(0), function (obj) {
2596+ return parseInt(obj, 10);
2597+ });
2598+ configFromArray(config);
2599+ } else if (isObject(input)) {
2600+ configFromObject(config);
2601+ } else if (isNumber(input)) {
2602+ // from milliseconds
2603+ config._d = new Date(input);
2604+ } else {
2605+ hooks.createFromInputFallback(config);
2606+ }
2607+ }
2608+
2609+ function createLocalOrUTC(input, format, locale, strict, isUTC) {
2610+ var c = {};
2611+
2612+ if (locale === true || locale === false) {
2613+ strict = locale;
2614+ locale = undefined;
2615+ }
2616+
2617+ if ((isObject(input) && isObjectEmpty(input)) ||
2618+ (isArray(input) && input.length === 0)) {
2619+ input = undefined;
2620+ }
2621+ // object construction must be done this way.
2622+ // https://github.com/moment/moment/issues/1423
2623+ c._isAMomentObject = true;
2624+ c._useUTC = c._isUTC = isUTC;
2625+ c._l = locale;
2626+ c._i = input;
2627+ c._f = format;
2628+ c._strict = strict;
2629+
2630+ return createFromConfig(c);
2631+ }
2632+
2633+ function createLocal(input, format, locale, strict) {
2634+ return createLocalOrUTC(input, format, locale, strict, false);
2635+ }
2636+
2637+ var prototypeMin = deprecate(
2638+ 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
2639+ function () {
2640+ var other = createLocal.apply(null, arguments);
2641+ if (this.isValid() && other.isValid()) {
2642+ return other < this ? this : other;
2643+ } else {
2644+ return createInvalid();
2645+ }
2646+ }
2647+ );
2648+
2649+ var prototypeMax = deprecate(
2650+ 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
2651+ function () {
2652+ var other = createLocal.apply(null, arguments);
2653+ if (this.isValid() && other.isValid()) {
2654+ return other > this ? this : other;
2655+ } else {
2656+ return createInvalid();
2657+ }
2658+ }
2659+ );
2660+
2661+ // Pick a moment m from moments so that m[fn](other) is true for all
2662+ // other. This relies on the function fn to be transitive.
2663+ //
2664+ // moments should either be an array of moment objects or an array, whose
2665+ // first element is an array of moment objects.
2666+ function pickBy(fn, moments) {
2667+ var res, i;
2668+ if (moments.length === 1 && isArray(moments[0])) {
2669+ moments = moments[0];
2670+ }
2671+ if (!moments.length) {
2672+ return createLocal();
2673+ }
2674+ res = moments[0];
2675+ for (i = 1; i < moments.length; ++i) {
2676+ if (!moments[i].isValid() || moments[i][fn](res)) {
2677+ res = moments[i];
2678+ }
2679+ }
2680+ return res;
2681+ }
2682+
2683+ // TODO: Use [].sort instead?
2684+ function min() {
2685+ var args = [].slice.call(arguments, 0);
2686+
2687+ return pickBy('isBefore', args);
2688+ }
2689+
2690+ function max() {
2691+ var args = [].slice.call(arguments, 0);
2692+
2693+ return pickBy('isAfter', args);
2694+ }
2695+
2696+ var now = function () {
2697+ return Date.now ? Date.now() : +(new Date());
2698+ };
2699+
2700+ var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
2701+
2702+ function isDurationValid(m) {
2703+ for (var key in m) {
2704+ if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
2705+ return false;
2706+ }
2707+ }
2708+
2709+ var unitHasDecimal = false;
2710+ for (var i = 0; i < ordering.length; ++i) {
2711+ if (m[ordering[i]]) {
2712+ if (unitHasDecimal) {
2713+ return false; // only allow non-integers for smallest unit
2714+ }
2715+ if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
2716+ unitHasDecimal = true;
2717+ }
2718+ }
2719+ }
2720+
2721+ return true;
2722+ }
2723+
2724+ function isValid$1() {
2725+ return this._isValid;
2726+ }
2727+
2728+ function createInvalid$1() {
2729+ return createDuration(NaN);
2730+ }
2731+
2732+ function Duration(duration) {
2733+ var normalizedInput = normalizeObjectUnits(duration),
2734+ years = normalizedInput.year || 0,
2735+ quarters = normalizedInput.quarter || 0,
2736+ months = normalizedInput.month || 0,
2737+ weeks = normalizedInput.week || 0,
2738+ days = normalizedInput.day || 0,
2739+ hours = normalizedInput.hour || 0,
2740+ minutes = normalizedInput.minute || 0,
2741+ seconds = normalizedInput.second || 0,
2742+ milliseconds = normalizedInput.millisecond || 0;
2743+
2744+ this._isValid = isDurationValid(normalizedInput);
2745+
2746+ // representation for dateAddRemove
2747+ this._milliseconds = +milliseconds +
2748+ seconds * 1e3 + // 1000
2749+ minutes * 6e4 + // 1000 * 60
2750+ hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
2751+ // Because of dateAddRemove treats 24 hours as different from a
2752+ // day when working around DST, we need to store them separately
2753+ this._days = +days +
2754+ weeks * 7;
2755+ // It is impossible to translate months into days without knowing
2756+ // which months you are are talking about, so we have to store
2757+ // it separately.
2758+ this._months = +months +
2759+ quarters * 3 +
2760+ years * 12;
2761+
2762+ this._data = {};
2763+
2764+ this._locale = getLocale();
2765+
2766+ this._bubble();
2767+ }
2768+
2769+ function isDuration(obj) {
2770+ return obj instanceof Duration;
2771+ }
2772+
2773+ function absRound(number) {
2774+ if (number < 0) {
2775+ return Math.round(-1 * number) * -1;
2776+ } else {
2777+ return Math.round(number);
2778+ }
2779+ }
2780+
2781+ // FORMATTING
2782+
2783+ function offset(token, separator) {
2784+ addFormatToken(token, 0, 0, function () {
2785+ var offset = this.utcOffset();
2786+ var sign = '+';
2787+ if (offset < 0) {
2788+ offset = -offset;
2789+ sign = '-';
2790+ }
2791+ return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
2792+ });
2793+ }
2794+
2795+ offset('Z', ':');
2796+ offset('ZZ', '');
2797+
2798+ // PARSING
2799+
2800+ addRegexToken('Z', matchShortOffset);
2801+ addRegexToken('ZZ', matchShortOffset);
2802+ addParseToken(['Z', 'ZZ'], function (input, array, config) {
2803+ config._useUTC = true;
2804+ config._tzm = offsetFromString(matchShortOffset, input);
2805+ });
2806+
2807+ // HELPERS
2808+
2809+ // timezone chunker
2810+ // '+10:00' > ['10', '00']
2811+ // '-1530' > ['-15', '30']
2812+ var chunkOffset = /([\+\-]|\d\d)/gi;
2813+
2814+ function offsetFromString(matcher, string) {
2815+ var matches = (string || '').match(matcher);
2816+
2817+ if (matches === null) {
2818+ return null;
2819+ }
2820+
2821+ var chunk = matches[matches.length - 1] || [];
2822+ var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
2823+ var minutes = +(parts[1] * 60) + toInt(parts[2]);
2824+
2825+ return minutes === 0 ?
2826+ 0 :
2827+ parts[0] === '+' ? minutes : -minutes;
2828+ }
2829+
2830+ // Return a moment from input, that is local/utc/zone equivalent to model.
2831+ function cloneWithOffset(input, model) {
2832+ var res, diff;
2833+ if (model._isUTC) {
2834+ res = model.clone();
2835+ diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
2836+ // Use low-level api, because this fn is low-level api.
2837+ res._d.setTime(res._d.valueOf() + diff);
2838+ hooks.updateOffset(res, false);
2839+ return res;
2840+ } else {
2841+ return createLocal(input).local();
2842+ }
2843+ }
2844+
2845+ function getDateOffset(m) {
2846+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
2847+ // https://github.com/moment/moment/pull/1871
2848+ return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
2849+ }
2850+
2851+ // HOOKS
2852+
2853+ // This function will be called whenever a moment is mutated.
2854+ // It is intended to keep the offset in sync with the timezone.
2855+ hooks.updateOffset = function () { };
2856+
2857+ // MOMENTS
2858+
2859+ // keepLocalTime = true means only change the timezone, without
2860+ // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
2861+ // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
2862+ // +0200, so we adjust the time as needed, to be valid.
2863+ //
2864+ // Keeping the time actually adds/subtracts (one hour)
2865+ // from the actual represented time. That is why we call updateOffset
2866+ // a second time. In case it wants us to change the offset again
2867+ // _changeInProgress == true case, then we have to adjust, because
2868+ // there is no such time in the given timezone.
2869+ function getSetOffset(input, keepLocalTime, keepMinutes) {
2870+ var offset = this._offset || 0,
2871+ localAdjust;
2872+ if (!this.isValid()) {
2873+ return input != null ? this : NaN;
2874+ }
2875+ if (input != null) {
2876+ if (typeof input === 'string') {
2877+ input = offsetFromString(matchShortOffset, input);
2878+ if (input === null) {
2879+ return this;
2880+ }
2881+ } else if (Math.abs(input) < 16 && !keepMinutes) {
2882+ input = input * 60;
2883+ }
2884+ if (!this._isUTC && keepLocalTime) {
2885+ localAdjust = getDateOffset(this);
2886+ }
2887+ this._offset = input;
2888+ this._isUTC = true;
2889+ if (localAdjust != null) {
2890+ this.add(localAdjust, 'm');
2891+ }
2892+ if (offset !== input) {
2893+ if (!keepLocalTime || this._changeInProgress) {
2894+ addSubtract(this, createDuration(input - offset, 'm'), 1, false);
2895+ } else if (!this._changeInProgress) {
2896+ this._changeInProgress = true;
2897+ hooks.updateOffset(this, true);
2898+ this._changeInProgress = null;
2899+ }
2900+ }
2901+ return this;
2902+ } else {
2903+ return this._isUTC ? offset : getDateOffset(this);
2904+ }
2905+ }
2906+
2907+ function getSetZone(input, keepLocalTime) {
2908+ if (input != null) {
2909+ if (typeof input !== 'string') {
2910+ input = -input;
2911+ }
2912+
2913+ this.utcOffset(input, keepLocalTime);
2914+
2915+ return this;
2916+ } else {
2917+ return -this.utcOffset();
2918+ }
2919+ }
2920+
2921+ function setOffsetToUTC(keepLocalTime) {
2922+ return this.utcOffset(0, keepLocalTime);
2923+ }
2924+
2925+ function setOffsetToLocal(keepLocalTime) {
2926+ if (this._isUTC) {
2927+ this.utcOffset(0, keepLocalTime);
2928+ this._isUTC = false;
2929+
2930+ if (keepLocalTime) {
2931+ this.subtract(getDateOffset(this), 'm');
2932+ }
2933+ }
2934+ return this;
2935+ }
2936+
2937+ function setOffsetToParsedOffset() {
2938+ if (this._tzm != null) {
2939+ this.utcOffset(this._tzm, false, true);
2940+ } else if (typeof this._i === 'string') {
2941+ var tZone = offsetFromString(matchOffset, this._i);
2942+ if (tZone != null) {
2943+ this.utcOffset(tZone);
2944+ }
2945+ else {
2946+ this.utcOffset(0, true);
2947+ }
2948+ }
2949+ return this;
2950+ }
2951+
2952+ function hasAlignedHourOffset(input) {
2953+ if (!this.isValid()) {
2954+ return false;
2955+ }
2956+ input = input ? createLocal(input).utcOffset() : 0;
2957+
2958+ return (this.utcOffset() - input) % 60 === 0;
2959+ }
2960+
2961+ function isDaylightSavingTime() {
2962+ return (
2963+ this.utcOffset() > this.clone().month(0).utcOffset() ||
2964+ this.utcOffset() > this.clone().month(5).utcOffset()
2965+ );
2966+ }
2967+
2968+ function isDaylightSavingTimeShifted() {
2969+ if (!isUndefined(this._isDSTShifted)) {
2970+ return this._isDSTShifted;
2971+ }
2972+
2973+ var c = {};
2974+
2975+ copyConfig(c, this);
2976+ c = prepareConfig(c);
2977+
2978+ if (c._a) {
2979+ var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
2980+ this._isDSTShifted = this.isValid() &&
2981+ compareArrays(c._a, other.toArray()) > 0;
2982+ } else {
2983+ this._isDSTShifted = false;
2984+ }
2985+
2986+ return this._isDSTShifted;
2987+ }
2988+
2989+ function isLocal() {
2990+ return this.isValid() ? !this._isUTC : false;
2991+ }
2992+
2993+ function isUtcOffset() {
2994+ return this.isValid() ? this._isUTC : false;
2995+ }
2996+
2997+ function isUtc() {
2998+ return this.isValid() ? this._isUTC && this._offset === 0 : false;
2999+ }
3000+
3001+ // ASP.NET json date format regex
3002+ var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
3003+
3004+ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
3005+ // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
3006+ // and further modified to allow for strings containing both week and day
3007+ var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
3008+
3009+ function createDuration(input, key) {
3010+ var duration = input,
3011+ // matching against regexp is expensive, do it on demand
3012+ match = null,
3013+ sign,
3014+ ret,
3015+ diffRes;
3016+
3017+ if (isDuration(input)) {
3018+ duration = {
3019+ ms: input._milliseconds,
3020+ d: input._days,
3021+ M: input._months
3022+ };
3023+ } else if (isNumber(input)) {
3024+ duration = {};
3025+ if (key) {
3026+ duration[key] = input;
3027+ } else {
3028+ duration.milliseconds = input;
3029+ }
3030+ } else if (!!(match = aspNetRegex.exec(input))) {
3031+ sign = (match[1] === '-') ? -1 : 1;
3032+ duration = {
3033+ y: 0,
3034+ d: toInt(match[DATE]) * sign,
3035+ h: toInt(match[HOUR]) * sign,
3036+ m: toInt(match[MINUTE]) * sign,
3037+ s: toInt(match[SECOND]) * sign,
3038+ ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
3039+ };
3040+ } else if (!!(match = isoRegex.exec(input))) {
3041+ sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
3042+ duration = {
3043+ y: parseIso(match[2], sign),
3044+ M: parseIso(match[3], sign),
3045+ w: parseIso(match[4], sign),
3046+ d: parseIso(match[5], sign),
3047+ h: parseIso(match[6], sign),
3048+ m: parseIso(match[7], sign),
3049+ s: parseIso(match[8], sign)
3050+ };
3051+ } else if (duration == null) {// checks for null or undefined
3052+ duration = {};
3053+ } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
3054+ diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
3055+
3056+ duration = {};
3057+ duration.ms = diffRes.milliseconds;
3058+ duration.M = diffRes.months;
3059+ }
3060+
3061+ ret = new Duration(duration);
3062+
3063+ if (isDuration(input) && hasOwnProp(input, '_locale')) {
3064+ ret._locale = input._locale;
3065+ }
3066+
3067+ return ret;
3068+ }
3069+
3070+ createDuration.fn = Duration.prototype;
3071+ createDuration.invalid = createInvalid$1;
3072+
3073+ function parseIso(inp, sign) {
3074+ // We'd normally use ~~inp for this, but unfortunately it also
3075+ // converts floats to ints.
3076+ // inp may be undefined, so careful calling replace on it.
3077+ var res = inp && parseFloat(inp.replace(',', '.'));
3078+ // apply sign while we're at it
3079+ return (isNaN(res) ? 0 : res) * sign;
3080+ }
3081+
3082+ function positiveMomentsDifference(base, other) {
3083+ var res = { milliseconds: 0, months: 0 };
3084+
3085+ res.months = other.month() - base.month() +
3086+ (other.year() - base.year()) * 12;
3087+ if (base.clone().add(res.months, 'M').isAfter(other)) {
3088+ --res.months;
3089+ }
3090+
3091+ res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
3092+
3093+ return res;
3094+ }
3095+
3096+ function momentsDifference(base, other) {
3097+ var res;
3098+ if (!(base.isValid() && other.isValid())) {
3099+ return { milliseconds: 0, months: 0 };
3100+ }
3101+
3102+ other = cloneWithOffset(other, base);
3103+ if (base.isBefore(other)) {
3104+ res = positiveMomentsDifference(base, other);
3105+ } else {
3106+ res = positiveMomentsDifference(other, base);
3107+ res.milliseconds = -res.milliseconds;
3108+ res.months = -res.months;
3109+ }
3110+
3111+ return res;
3112+ }
3113+
3114+ // TODO: remove 'name' arg after deprecation is removed
3115+ function createAdder(direction, name) {
3116+ return function (val, period) {
3117+ var dur, tmp;
3118+ //invert the arguments, but complain about it
3119+ if (period !== null && !isNaN(+period)) {
3120+ deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
3121+ 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
3122+ tmp = val; val = period; period = tmp;
3123+ }
3124+
3125+ val = typeof val === 'string' ? +val : val;
3126+ dur = createDuration(val, period);
3127+ addSubtract(this, dur, direction);
3128+ return this;
3129+ };
3130+ }
3131+
3132+ function addSubtract(mom, duration, isAdding, updateOffset) {
3133+ var milliseconds = duration._milliseconds,
3134+ days = absRound(duration._days),
3135+ months = absRound(duration._months);
3136+
3137+ if (!mom.isValid()) {
3138+ // No op
3139+ return;
3140+ }
3141+
3142+ updateOffset = updateOffset == null ? true : updateOffset;
3143+
3144+ if (months) {
3145+ setMonth(mom, get(mom, 'Month') + months * isAdding);
3146+ }
3147+ if (days) {
3148+ set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
3149+ }
3150+ if (milliseconds) {
3151+ mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
3152+ }
3153+ if (updateOffset) {
3154+ hooks.updateOffset(mom, days || months);
3155+ }
3156+ }
3157+
3158+ var add = createAdder(1, 'add');
3159+ var subtract = createAdder(-1, 'subtract');
3160+
3161+ function getCalendarFormat(myMoment, now) {
3162+ var diff = myMoment.diff(now, 'days', true);
3163+ return diff < -6 ? 'sameElse' :
3164+ diff < -1 ? 'lastWeek' :
3165+ diff < 0 ? 'lastDay' :
3166+ diff < 1 ? 'sameDay' :
3167+ diff < 2 ? 'nextDay' :
3168+ diff < 7 ? 'nextWeek' : 'sameElse';
3169+ }
3170+
3171+ function calendar$1(time, formats) {
3172+ // We want to compare the start of today, vs this.
3173+ // Getting start-of-today depends on whether we're local/utc/offset or not.
3174+ var now = time || createLocal(),
3175+ sod = cloneWithOffset(now, this).startOf('day'),
3176+ format = hooks.calendarFormat(this, sod) || 'sameElse';
3177+
3178+ var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
3179+
3180+ return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
3181+ }
3182+
3183+ function clone() {
3184+ return new Moment(this);
3185+ }
3186+
3187+ function isAfter(input, units) {
3188+ var localInput = isMoment(input) ? input : createLocal(input);
3189+ if (!(this.isValid() && localInput.isValid())) {
3190+ return false;
3191+ }
3192+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
3193+ if (units === 'millisecond') {
3194+ return this.valueOf() > localInput.valueOf();
3195+ } else {
3196+ return localInput.valueOf() < this.clone().startOf(units).valueOf();
3197+ }
3198+ }
3199+
3200+ function isBefore(input, units) {
3201+ var localInput = isMoment(input) ? input : createLocal(input);
3202+ if (!(this.isValid() && localInput.isValid())) {
3203+ return false;
3204+ }
3205+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
3206+ if (units === 'millisecond') {
3207+ return this.valueOf() < localInput.valueOf();
3208+ } else {
3209+ return this.clone().endOf(units).valueOf() < localInput.valueOf();
3210+ }
3211+ }
3212+
3213+ function isBetween(from, to, units, inclusivity) {
3214+ inclusivity = inclusivity || '()';
3215+ return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
3216+ (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
3217+ }
3218+
3219+ function isSame(input, units) {
3220+ var localInput = isMoment(input) ? input : createLocal(input),
3221+ inputMs;
3222+ if (!(this.isValid() && localInput.isValid())) {
3223+ return false;
3224+ }
3225+ units = normalizeUnits(units || 'millisecond');
3226+ if (units === 'millisecond') {
3227+ return this.valueOf() === localInput.valueOf();
3228+ } else {
3229+ inputMs = localInput.valueOf();
3230+ return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
3231+ }
3232+ }
3233+
3234+ function isSameOrAfter(input, units) {
3235+ return this.isSame(input, units) || this.isAfter(input, units);
3236+ }
3237+
3238+ function isSameOrBefore(input, units) {
3239+ return this.isSame(input, units) || this.isBefore(input, units);
3240+ }
3241+
3242+ function diff(input, units, asFloat) {
3243+ var that,
3244+ zoneDelta,
3245+ delta, output;
3246+
3247+ if (!this.isValid()) {
3248+ return NaN;
3249+ }
3250+
3251+ that = cloneWithOffset(input, this);
3252+
3253+ if (!that.isValid()) {
3254+ return NaN;
3255+ }
3256+
3257+ zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
3258+
3259+ units = normalizeUnits(units);
3260+
3261+ switch (units) {
3262+ case 'year': output = monthDiff(this, that) / 12; break;
3263+ case 'month': output = monthDiff(this, that); break;
3264+ case 'quarter': output = monthDiff(this, that) / 3; break;
3265+ case 'second': output = (this - that) / 1e3; break; // 1000
3266+ case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
3267+ case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
3268+ case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
3269+ case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
3270+ default: output = this - that;
3271+ }
3272+
3273+ return asFloat ? output : absFloor(output);
3274+ }
3275+
3276+ function monthDiff(a, b) {
3277+ // difference in months
3278+ var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
3279+ // b is in (anchor - 1 month, anchor + 1 month)
3280+ anchor = a.clone().add(wholeMonthDiff, 'months'),
3281+ anchor2, adjust;
3282+
3283+ if (b - anchor < 0) {
3284+ anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
3285+ // linear across the month
3286+ adjust = (b - anchor) / (anchor - anchor2);
3287+ } else {
3288+ anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
3289+ // linear across the month
3290+ adjust = (b - anchor) / (anchor2 - anchor);
3291+ }
3292+
3293+ //check for negative zero, return zero if negative zero
3294+ return -(wholeMonthDiff + adjust) || 0;
3295+ }
3296+
3297+ hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
3298+ hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
3299+
3300+ function toString() {
3301+ return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
3302+ }
3303+
3304+ function toISOString(keepOffset) {
3305+ if (!this.isValid()) {
3306+ return null;
3307+ }
3308+ var utc = keepOffset !== true;
3309+ var m = utc ? this.clone().utc() : this;
3310+ if (m.year() < 0 || m.year() > 9999) {
3311+ return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
3312+ }
3313+ if (isFunction(Date.prototype.toISOString)) {
3314+ // native implementation is ~50x faster, use it when we can
3315+ if (utc) {
3316+ return this.toDate().toISOString();
3317+ } else {
3318+ return new Date(this._d.valueOf()).toISOString().replace('Z', formatMoment(m, 'Z'));
3319+ }
3320+ }
3321+ return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
3322+ }
3323+
3324+ /**
3325+ * Return a human readable representation of a moment that can
3326+ * also be evaluated to get a new moment which is the same
3327+ *
3328+ * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
3329+ */
3330+ function inspect() {
3331+ if (!this.isValid()) {
3332+ return 'moment.invalid(/* ' + this._i + ' */)';
3333+ }
3334+ var func = 'moment';
3335+ var zone = '';
3336+ if (!this.isLocal()) {
3337+ func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
3338+ zone = 'Z';
3339+ }
3340+ var prefix = '[' + func + '("]';
3341+ var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
3342+ var datetime = '-MM-DD[T]HH:mm:ss.SSS';
3343+ var suffix = zone + '[")]';
3344+
3345+ return this.format(prefix + year + datetime + suffix);
3346+ }

1942 more lines aren’t shown here.

Source/package.json+1−1
@@ -17,7 +17,7 @@ · 16 unmodified lines
1717 "knockout.observableDictionary.js": "Unavailable",
1818 "knockout.reactor.js": "1.3.0",
1919 "knockout.validation.js": "2.0.3",
20− "moment": "2.9.0",
20+ "moment": "2.20.1",
2121 "primeui": "Unavailable",
2222 "flot": "Unavailable"
2323 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t