]> git.mxchange.org Git - friendica.git/blob - library/moment/moment.js
Merge branch 'master' of github.com:annando/friendica
[friendica.git] / library / moment / moment.js
1 //! moment.js
2 //! version : 2.15.1
3 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4 //! license : MIT
5 //! momentjs.com
6
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 () { 'use strict';
12
13     var hookCallback;
14
15     function utils_hooks__hooks () {
16         return hookCallback.apply(null, arguments);
17     }
18
19     // This is done to register the method called with moment()
20     // without creating circular dependencies.
21     function setHookCallback (callback) {
22         hookCallback = callback;
23     }
24
25     function isArray(input) {
26         return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
27     }
28
29     function isObject(input) {
30         // IE8 will treat undefined and null as object if it wasn't for
31         // input != null
32         return input != null && Object.prototype.toString.call(input) === '[object Object]';
33     }
34
35     function isObjectEmpty(obj) {
36         var k;
37         for (k in obj) {
38             // even if its not own property I'd still call it non-empty
39             return false;
40         }
41         return true;
42     }
43
44     function isDate(input) {
45         return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
46     }
47
48     function map(arr, fn) {
49         var res = [], i;
50         for (i = 0; i < arr.length; ++i) {
51             res.push(fn(arr[i], i));
52         }
53         return res;
54     }
55
56     function hasOwnProp(a, b) {
57         return Object.prototype.hasOwnProperty.call(a, b);
58     }
59
60     function extend(a, b) {
61         for (var i in b) {
62             if (hasOwnProp(b, i)) {
63                 a[i] = b[i];
64             }
65         }
66
67         if (hasOwnProp(b, 'toString')) {
68             a.toString = b.toString;
69         }
70
71         if (hasOwnProp(b, 'valueOf')) {
72             a.valueOf = b.valueOf;
73         }
74
75         return a;
76     }
77
78     function create_utc__createUTC (input, format, locale, strict) {
79         return createLocalOrUTC(input, format, locale, strict, true).utc();
80     }
81
82     function defaultParsingFlags() {
83         // We need to deep clone this object.
84         return {
85             empty           : false,
86             unusedTokens    : [],
87             unusedInput     : [],
88             overflow        : -2,
89             charsLeftOver   : 0,
90             nullInput       : false,
91             invalidMonth    : null,
92             invalidFormat   : false,
93             userInvalidated : false,
94             iso             : false,
95             parsedDateParts : [],
96             meridiem        : null
97         };
98     }
99
100     function getParsingFlags(m) {
101         if (m._pf == null) {
102             m._pf = defaultParsingFlags();
103         }
104         return m._pf;
105     }
106
107     var some;
108     if (Array.prototype.some) {
109         some = Array.prototype.some;
110     } else {
111         some = function (fun) {
112             var t = Object(this);
113             var len = t.length >>> 0;
114
115             for (var i = 0; i < len; i++) {
116                 if (i in t && fun.call(this, t[i], i, t)) {
117                     return true;
118                 }
119             }
120
121             return false;
122         };
123     }
124
125     function valid__isValid(m) {
126         if (m._isValid == null) {
127             var flags = getParsingFlags(m);
128             var parsedParts = some.call(flags.parsedDateParts, function (i) {
129                 return i != null;
130             });
131             var isNowValid = !isNaN(m._d.getTime()) &&
132                 flags.overflow < 0 &&
133                 !flags.empty &&
134                 !flags.invalidMonth &&
135                 !flags.invalidWeekday &&
136                 !flags.nullInput &&
137                 !flags.invalidFormat &&
138                 !flags.userInvalidated &&
139                 (!flags.meridiem || (flags.meridiem && parsedParts));
140
141             if (m._strict) {
142                 isNowValid = isNowValid &&
143                     flags.charsLeftOver === 0 &&
144                     flags.unusedTokens.length === 0 &&
145                     flags.bigHour === undefined;
146             }
147
148             if (Object.isFrozen == null || !Object.isFrozen(m)) {
149                 m._isValid = isNowValid;
150             }
151             else {
152                 return isNowValid;
153             }
154         }
155         return m._isValid;
156     }
157
158     function valid__createInvalid (flags) {
159         var m = create_utc__createUTC(NaN);
160         if (flags != null) {
161             extend(getParsingFlags(m), flags);
162         }
163         else {
164             getParsingFlags(m).userInvalidated = true;
165         }
166
167         return m;
168     }
169
170     function isUndefined(input) {
171         return input === void 0;
172     }
173
174     // Plugins that add properties should also add the key here (null value),
175     // so we can properly clone ourselves.
176     var momentProperties = utils_hooks__hooks.momentProperties = [];
177
178     function copyConfig(to, from) {
179         var i, prop, val;
180
181         if (!isUndefined(from._isAMomentObject)) {
182             to._isAMomentObject = from._isAMomentObject;
183         }
184         if (!isUndefined(from._i)) {
185             to._i = from._i;
186         }
187         if (!isUndefined(from._f)) {
188             to._f = from._f;
189         }
190         if (!isUndefined(from._l)) {
191             to._l = from._l;
192         }
193         if (!isUndefined(from._strict)) {
194             to._strict = from._strict;
195         }
196         if (!isUndefined(from._tzm)) {
197             to._tzm = from._tzm;
198         }
199         if (!isUndefined(from._isUTC)) {
200             to._isUTC = from._isUTC;
201         }
202         if (!isUndefined(from._offset)) {
203             to._offset = from._offset;
204         }
205         if (!isUndefined(from._pf)) {
206             to._pf = getParsingFlags(from);
207         }
208         if (!isUndefined(from._locale)) {
209             to._locale = from._locale;
210         }
211
212         if (momentProperties.length > 0) {
213             for (i in momentProperties) {
214                 prop = momentProperties[i];
215                 val = from[prop];
216                 if (!isUndefined(val)) {
217                     to[prop] = val;
218                 }
219             }
220         }
221
222         return to;
223     }
224
225     var updateInProgress = false;
226
227     // Moment prototype object
228     function Moment(config) {
229         copyConfig(this, config);
230         this._d = new Date(config._d != null ? config._d.getTime() : NaN);
231         // Prevent infinite loop in case updateOffset creates new moment
232         // objects.
233         if (updateInProgress === false) {
234             updateInProgress = true;
235             utils_hooks__hooks.updateOffset(this);
236             updateInProgress = false;
237         }
238     }
239
240     function isMoment (obj) {
241         return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
242     }
243
244     function absFloor (number) {
245         if (number < 0) {
246             // -0 -> 0
247             return Math.ceil(number) || 0;
248         } else {
249             return Math.floor(number);
250         }
251     }
252
253     function toInt(argumentForCoercion) {
254         var coercedNumber = +argumentForCoercion,
255             value = 0;
256
257         if (coercedNumber !== 0 && isFinite(coercedNumber)) {
258             value = absFloor(coercedNumber);
259         }
260
261         return value;
262     }
263
264     // compare two arrays, return the number of differences
265     function compareArrays(array1, array2, dontConvert) {
266         var len = Math.min(array1.length, array2.length),
267             lengthDiff = Math.abs(array1.length - array2.length),
268             diffs = 0,
269             i;
270         for (i = 0; i < len; i++) {
271             if ((dontConvert && array1[i] !== array2[i]) ||
272                 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
273                 diffs++;
274             }
275         }
276         return diffs + lengthDiff;
277     }
278
279     function warn(msg) {
280         if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
281                 (typeof console !==  'undefined') && console.warn) {
282             console.warn('Deprecation warning: ' + msg);
283         }
284     }
285
286     function deprecate(msg, fn) {
287         var firstTime = true;
288
289         return extend(function () {
290             if (utils_hooks__hooks.deprecationHandler != null) {
291                 utils_hooks__hooks.deprecationHandler(null, msg);
292             }
293             if (firstTime) {
294                 var args = [];
295                 var arg;
296                 for (var i = 0; i < arguments.length; i++) {
297                     arg = '';
298                     if (typeof arguments[i] === 'object') {
299                         arg += '\n[' + i + '] ';
300                         for (var key in arguments[0]) {
301                             arg += key + ': ' + arguments[0][key] + ', ';
302                         }
303                         arg = arg.slice(0, -2); // Remove trailing comma and space
304                     } else {
305                         arg = arguments[i];
306                     }
307                     args.push(arg);
308                 }
309                 warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
310                 firstTime = false;
311             }
312             return fn.apply(this, arguments);
313         }, fn);
314     }
315
316     var deprecations = {};
317
318     function deprecateSimple(name, msg) {
319         if (utils_hooks__hooks.deprecationHandler != null) {
320             utils_hooks__hooks.deprecationHandler(name, msg);
321         }
322         if (!deprecations[name]) {
323             warn(msg);
324             deprecations[name] = true;
325         }
326     }
327
328     utils_hooks__hooks.suppressDeprecationWarnings = false;
329     utils_hooks__hooks.deprecationHandler = null;
330
331     function isFunction(input) {
332         return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
333     }
334
335     function locale_set__set (config) {
336         var prop, i;
337         for (i in config) {
338             prop = config[i];
339             if (isFunction(prop)) {
340                 this[i] = prop;
341             } else {
342                 this['_' + i] = prop;
343             }
344         }
345         this._config = config;
346         // Lenient ordinal parsing accepts just a number in addition to
347         // number + (possibly) stuff coming from _ordinalParseLenient.
348         this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
349     }
350
351     function mergeConfigs(parentConfig, childConfig) {
352         var res = extend({}, parentConfig), prop;
353         for (prop in childConfig) {
354             if (hasOwnProp(childConfig, prop)) {
355                 if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
356                     res[prop] = {};
357                     extend(res[prop], parentConfig[prop]);
358                     extend(res[prop], childConfig[prop]);
359                 } else if (childConfig[prop] != null) {
360                     res[prop] = childConfig[prop];
361                 } else {
362                     delete res[prop];
363                 }
364             }
365         }
366         for (prop in parentConfig) {
367             if (hasOwnProp(parentConfig, prop) &&
368                     !hasOwnProp(childConfig, prop) &&
369                     isObject(parentConfig[prop])) {
370                 // make sure changes to properties don't modify parent config
371                 res[prop] = extend({}, res[prop]);
372             }
373         }
374         return res;
375     }
376
377     function Locale(config) {
378         if (config != null) {
379             this.set(config);
380         }
381     }
382
383     var keys;
384
385     if (Object.keys) {
386         keys = Object.keys;
387     } else {
388         keys = function (obj) {
389             var i, res = [];
390             for (i in obj) {
391                 if (hasOwnProp(obj, i)) {
392                     res.push(i);
393                 }
394             }
395             return res;
396         };
397     }
398
399     var defaultCalendar = {
400         sameDay : '[Today at] LT',
401         nextDay : '[Tomorrow at] LT',
402         nextWeek : 'dddd [at] LT',
403         lastDay : '[Yesterday at] LT',
404         lastWeek : '[Last] dddd [at] LT',
405         sameElse : 'L'
406     };
407
408     function locale_calendar__calendar (key, mom, now) {
409         var output = this._calendar[key] || this._calendar['sameElse'];
410         return isFunction(output) ? output.call(mom, now) : output;
411     }
412
413     var defaultLongDateFormat = {
414         LTS  : 'h:mm:ss A',
415         LT   : 'h:mm A',
416         L    : 'MM/DD/YYYY',
417         LL   : 'MMMM D, YYYY',
418         LLL  : 'MMMM D, YYYY h:mm A',
419         LLLL : 'dddd, MMMM D, YYYY h:mm A'
420     };
421
422     function longDateFormat (key) {
423         var format = this._longDateFormat[key],
424             formatUpper = this._longDateFormat[key.toUpperCase()];
425
426         if (format || !formatUpper) {
427             return format;
428         }
429
430         this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
431             return val.slice(1);
432         });
433
434         return this._longDateFormat[key];
435     }
436
437     var defaultInvalidDate = 'Invalid date';
438
439     function invalidDate () {
440         return this._invalidDate;
441     }
442
443     var defaultOrdinal = '%d';
444     var defaultOrdinalParse = /\d{1,2}/;
445
446     function ordinal (number) {
447         return this._ordinal.replace('%d', number);
448     }
449
450     var defaultRelativeTime = {
451         future : 'in %s',
452         past   : '%s ago',
453         s  : 'a few seconds',
454         m  : 'a minute',
455         mm : '%d minutes',
456         h  : 'an hour',
457         hh : '%d hours',
458         d  : 'a day',
459         dd : '%d days',
460         M  : 'a month',
461         MM : '%d months',
462         y  : 'a year',
463         yy : '%d years'
464     };
465
466     function relative__relativeTime (number, withoutSuffix, string, isFuture) {
467         var output = this._relativeTime[string];
468         return (isFunction(output)) ?
469             output(number, withoutSuffix, string, isFuture) :
470             output.replace(/%d/i, number);
471     }
472
473     function pastFuture (diff, output) {
474         var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
475         return isFunction(format) ? format(output) : format.replace(/%s/i, output);
476     }
477
478     var aliases = {};
479
480     function addUnitAlias (unit, shorthand) {
481         var lowerCase = unit.toLowerCase();
482         aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
483     }
484
485     function normalizeUnits(units) {
486         return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
487     }
488
489     function normalizeObjectUnits(inputObject) {
490         var normalizedInput = {},
491             normalizedProp,
492             prop;
493
494         for (prop in inputObject) {
495             if (hasOwnProp(inputObject, prop)) {
496                 normalizedProp = normalizeUnits(prop);
497                 if (normalizedProp) {
498                     normalizedInput[normalizedProp] = inputObject[prop];
499                 }
500             }
501         }
502
503         return normalizedInput;
504     }
505
506     var priorities = {};
507
508     function addUnitPriority(unit, priority) {
509         priorities[unit] = priority;
510     }
511
512     function getPrioritizedUnits(unitsObj) {
513         var units = [];
514         for (var u in unitsObj) {
515             units.push({unit: u, priority: priorities[u]});
516         }
517         units.sort(function (a, b) {
518             return a.priority - b.priority;
519         });
520         return units;
521     }
522
523     function makeGetSet (unit, keepTime) {
524         return function (value) {
525             if (value != null) {
526                 get_set__set(this, unit, value);
527                 utils_hooks__hooks.updateOffset(this, keepTime);
528                 return this;
529             } else {
530                 return get_set__get(this, unit);
531             }
532         };
533     }
534
535     function get_set__get (mom, unit) {
536         return mom.isValid() ?
537             mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
538     }
539
540     function get_set__set (mom, unit, value) {
541         if (mom.isValid()) {
542             mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
543         }
544     }
545
546     // MOMENTS
547
548     function stringGet (units) {
549         units = normalizeUnits(units);
550         if (isFunction(this[units])) {
551             return this[units]();
552         }
553         return this;
554     }
555
556
557     function stringSet (units, value) {
558         if (typeof units === 'object') {
559             units = normalizeObjectUnits(units);
560             var prioritized = getPrioritizedUnits(units);
561             for (var i = 0; i < prioritized.length; i++) {
562                 this[prioritized[i].unit](units[prioritized[i].unit]);
563             }
564         } else {
565             units = normalizeUnits(units);
566             if (isFunction(this[units])) {
567                 return this[units](value);
568             }
569         }
570         return this;
571     }
572
573     function zeroFill(number, targetLength, forceSign) {
574         var absNumber = '' + Math.abs(number),
575             zerosToFill = targetLength - absNumber.length,
576             sign = number >= 0;
577         return (sign ? (forceSign ? '+' : '') : '-') +
578             Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
579     }
580
581     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;
582
583     var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
584
585     var formatFunctions = {};
586
587     var formatTokenFunctions = {};
588
589     // token:    'M'
590     // padded:   ['MM', 2]
591     // ordinal:  'Mo'
592     // callback: function () { this.month() + 1 }
593     function addFormatToken (token, padded, ordinal, callback) {
594         var func = callback;
595         if (typeof callback === 'string') {
596             func = function () {
597                 return this[callback]();
598             };
599         }
600         if (token) {
601             formatTokenFunctions[token] = func;
602         }
603         if (padded) {
604             formatTokenFunctions[padded[0]] = function () {
605                 return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
606             };
607         }
608         if (ordinal) {
609             formatTokenFunctions[ordinal] = function () {
610                 return this.localeData().ordinal(func.apply(this, arguments), token);
611             };
612         }
613     }
614
615     function removeFormattingTokens(input) {
616         if (input.match(/\[[\s\S]/)) {
617             return input.replace(/^\[|\]$/g, '');
618         }
619         return input.replace(/\\/g, '');
620     }
621
622     function makeFormatFunction(format) {
623         var array = format.match(formattingTokens), i, length;
624
625         for (i = 0, length = array.length; i < length; i++) {
626             if (formatTokenFunctions[array[i]]) {
627                 array[i] = formatTokenFunctions[array[i]];
628             } else {
629                 array[i] = removeFormattingTokens(array[i]);
630             }
631         }
632
633         return function (mom) {
634             var output = '', i;
635             for (i = 0; i < length; i++) {
636                 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
637             }
638             return output;
639         };
640     }
641
642     // format date using native date object
643     function formatMoment(m, format) {
644         if (!m.isValid()) {
645             return m.localeData().invalidDate();
646         }
647
648         format = expandFormat(format, m.localeData());
649         formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
650
651         return formatFunctions[format](m);
652     }
653
654     function expandFormat(format, locale) {
655         var i = 5;
656
657         function replaceLongDateFormatTokens(input) {
658             return locale.longDateFormat(input) || input;
659         }
660
661         localFormattingTokens.lastIndex = 0;
662         while (i >= 0 && localFormattingTokens.test(format)) {
663             format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
664             localFormattingTokens.lastIndex = 0;
665             i -= 1;
666         }
667
668         return format;
669     }
670
671     var match1         = /\d/;            //       0 - 9
672     var match2         = /\d\d/;          //      00 - 99
673     var match3         = /\d{3}/;         //     000 - 999
674     var match4         = /\d{4}/;         //    0000 - 9999
675     var match6         = /[+-]?\d{6}/;    // -999999 - 999999
676     var match1to2      = /\d\d?/;         //       0 - 99
677     var match3to4      = /\d\d\d\d?/;     //     999 - 9999
678     var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
679     var match1to3      = /\d{1,3}/;       //       0 - 999
680     var match1to4      = /\d{1,4}/;       //       0 - 9999
681     var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
682
683     var matchUnsigned  = /\d+/;           //       0 - inf
684     var matchSigned    = /[+-]?\d+/;      //    -inf - inf
685
686     var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
687     var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
688
689     var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
690
691     // any word (or two) characters or numbers including two/three word month in arabic.
692     // includes scottish gaelic two word and hyphenated months
693     var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
694
695
696     var regexes = {};
697
698     function addRegexToken (token, regex, strictRegex) {
699         regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
700             return (isStrict && strictRegex) ? strictRegex : regex;
701         };
702     }
703
704     function getParseRegexForToken (token, config) {
705         if (!hasOwnProp(regexes, token)) {
706             return new RegExp(unescapeFormat(token));
707         }
708
709         return regexes[token](config._strict, config._locale);
710     }
711
712     // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
713     function unescapeFormat(s) {
714         return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
715             return p1 || p2 || p3 || p4;
716         }));
717     }
718
719     function regexEscape(s) {
720         return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
721     }
722
723     var tokens = {};
724
725     function addParseToken (token, callback) {
726         var i, func = callback;
727         if (typeof token === 'string') {
728             token = [token];
729         }
730         if (typeof callback === 'number') {
731             func = function (input, array) {
732                 array[callback] = toInt(input);
733             };
734         }
735         for (i = 0; i < token.length; i++) {
736             tokens[token[i]] = func;
737         }
738     }
739
740     function addWeekParseToken (token, callback) {
741         addParseToken(token, function (input, array, config, token) {
742             config._w = config._w || {};
743             callback(input, config._w, config, token);
744         });
745     }
746
747     function addTimeToArrayFromToken(token, input, config) {
748         if (input != null && hasOwnProp(tokens, token)) {
749             tokens[token](input, config._a, config, token);
750         }
751     }
752
753     var YEAR = 0;
754     var MONTH = 1;
755     var DATE = 2;
756     var HOUR = 3;
757     var MINUTE = 4;
758     var SECOND = 5;
759     var MILLISECOND = 6;
760     var WEEK = 7;
761     var WEEKDAY = 8;
762
763     var indexOf;
764
765     if (Array.prototype.indexOf) {
766         indexOf = Array.prototype.indexOf;
767     } else {
768         indexOf = function (o) {
769             // I know
770             var i;
771             for (i = 0; i < this.length; ++i) {
772                 if (this[i] === o) {
773                     return i;
774                 }
775             }
776             return -1;
777         };
778     }
779
780     function daysInMonth(year, month) {
781         return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
782     }
783
784     // FORMATTING
785
786     addFormatToken('M', ['MM', 2], 'Mo', function () {
787         return this.month() + 1;
788     });
789
790     addFormatToken('MMM', 0, 0, function (format) {
791         return this.localeData().monthsShort(this, format);
792     });
793
794     addFormatToken('MMMM', 0, 0, function (format) {
795         return this.localeData().months(this, format);
796     });
797
798     // ALIASES
799
800     addUnitAlias('month', 'M');
801
802     // PRIORITY
803
804     addUnitPriority('month', 8);
805
806     // PARSING
807
808     addRegexToken('M',    match1to2);
809     addRegexToken('MM',   match1to2, match2);
810     addRegexToken('MMM',  function (isStrict, locale) {
811         return locale.monthsShortRegex(isStrict);
812     });
813     addRegexToken('MMMM', function (isStrict, locale) {
814         return locale.monthsRegex(isStrict);
815     });
816
817     addParseToken(['M', 'MM'], function (input, array) {
818         array[MONTH] = toInt(input) - 1;
819     });
820
821     addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
822         var month = config._locale.monthsParse(input, token, config._strict);
823         // if we didn't find a month name, mark the date as invalid.
824         if (month != null) {
825             array[MONTH] = month;
826         } else {
827             getParsingFlags(config).invalidMonth = input;
828         }
829     });
830
831     // LOCALES
832
833     var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
834     var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
835     function localeMonths (m, format) {
836         if (!m) {
837             return this._months;
838         }
839         return isArray(this._months) ? this._months[m.month()] :
840             this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
841     }
842
843     var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
844     function localeMonthsShort (m, format) {
845         if (!m) {
846             return this._monthsShort;
847         }
848         return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
849             this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
850     }
851
852     function units_month__handleStrictParse(monthName, format, strict) {
853         var i, ii, mom, llc = monthName.toLocaleLowerCase();
854         if (!this._monthsParse) {
855             // this is not used
856             this._monthsParse = [];
857             this._longMonthsParse = [];
858             this._shortMonthsParse = [];
859             for (i = 0; i < 12; ++i) {
860                 mom = create_utc__createUTC([2000, i]);
861                 this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
862                 this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
863             }
864         }
865
866         if (strict) {
867             if (format === 'MMM') {
868                 ii = indexOf.call(this._shortMonthsParse, llc);
869                 return ii !== -1 ? ii : null;
870             } else {
871                 ii = indexOf.call(this._longMonthsParse, llc);
872                 return ii !== -1 ? ii : null;
873             }
874         } else {
875             if (format === 'MMM') {
876                 ii = indexOf.call(this._shortMonthsParse, llc);
877                 if (ii !== -1) {
878                     return ii;
879                 }
880                 ii = indexOf.call(this._longMonthsParse, llc);
881                 return ii !== -1 ? ii : null;
882             } else {
883                 ii = indexOf.call(this._longMonthsParse, llc);
884                 if (ii !== -1) {
885                     return ii;
886                 }
887                 ii = indexOf.call(this._shortMonthsParse, llc);
888                 return ii !== -1 ? ii : null;
889             }
890         }
891     }
892
893     function localeMonthsParse (monthName, format, strict) {
894         var i, mom, regex;
895
896         if (this._monthsParseExact) {
897             return units_month__handleStrictParse.call(this, monthName, format, strict);
898         }
899
900         if (!this._monthsParse) {
901             this._monthsParse = [];
902             this._longMonthsParse = [];
903             this._shortMonthsParse = [];
904         }
905
906         // TODO: add sorting
907         // Sorting makes sure if one month (or abbr) is a prefix of another
908         // see sorting in computeMonthsParse
909         for (i = 0; i < 12; i++) {
910             // make the regex if we don't have it already
911             mom = create_utc__createUTC([2000, i]);
912             if (strict && !this._longMonthsParse[i]) {
913                 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
914                 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
915             }
916             if (!strict && !this._monthsParse[i]) {
917                 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
918                 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
919             }
920             // test the regex
921             if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
922                 return i;
923             } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
924                 return i;
925             } else if (!strict && this._monthsParse[i].test(monthName)) {
926                 return i;
927             }
928         }
929     }
930
931     // MOMENTS
932
933     function setMonth (mom, value) {
934         var dayOfMonth;
935
936         if (!mom.isValid()) {
937             // No op
938             return mom;
939         }
940
941         if (typeof value === 'string') {
942             if (/^\d+$/.test(value)) {
943                 value = toInt(value);
944             } else {
945                 value = mom.localeData().monthsParse(value);
946                 // TODO: Another silent failure?
947                 if (typeof value !== 'number') {
948                     return mom;
949                 }
950             }
951         }
952
953         dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
954         mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
955         return mom;
956     }
957
958     function getSetMonth (value) {
959         if (value != null) {
960             setMonth(this, value);
961             utils_hooks__hooks.updateOffset(this, true);
962             return this;
963         } else {
964             return get_set__get(this, 'Month');
965         }
966     }
967
968     function getDaysInMonth () {
969         return daysInMonth(this.year(), this.month());
970     }
971
972     var defaultMonthsShortRegex = matchWord;
973     function monthsShortRegex (isStrict) {
974         if (this._monthsParseExact) {
975             if (!hasOwnProp(this, '_monthsRegex')) {
976                 computeMonthsParse.call(this);
977             }
978             if (isStrict) {
979                 return this._monthsShortStrictRegex;
980             } else {
981                 return this._monthsShortRegex;
982             }
983         } else {
984             if (!hasOwnProp(this, '_monthsShortRegex')) {
985                 this._monthsShortRegex = defaultMonthsShortRegex;
986             }
987             return this._monthsShortStrictRegex && isStrict ?
988                 this._monthsShortStrictRegex : this._monthsShortRegex;
989         }
990     }
991
992     var defaultMonthsRegex = matchWord;
993     function monthsRegex (isStrict) {
994         if (this._monthsParseExact) {
995             if (!hasOwnProp(this, '_monthsRegex')) {
996                 computeMonthsParse.call(this);
997             }
998             if (isStrict) {
999                 return this._monthsStrictRegex;
1000             } else {
1001                 return this._monthsRegex;
1002             }
1003         } else {
1004             if (!hasOwnProp(this, '_monthsRegex')) {
1005                 this._monthsRegex = defaultMonthsRegex;
1006             }
1007             return this._monthsStrictRegex && isStrict ?
1008                 this._monthsStrictRegex : this._monthsRegex;
1009         }
1010     }
1011
1012     function computeMonthsParse () {
1013         function cmpLenRev(a, b) {
1014             return b.length - a.length;
1015         }
1016
1017         var shortPieces = [], longPieces = [], mixedPieces = [],
1018             i, mom;
1019         for (i = 0; i < 12; i++) {
1020             // make the regex if we don't have it already
1021             mom = create_utc__createUTC([2000, i]);
1022             shortPieces.push(this.monthsShort(mom, ''));
1023             longPieces.push(this.months(mom, ''));
1024             mixedPieces.push(this.months(mom, ''));
1025             mixedPieces.push(this.monthsShort(mom, ''));
1026         }
1027         // Sorting makes sure if one month (or abbr) is a prefix of another it
1028         // will match the longer piece.
1029         shortPieces.sort(cmpLenRev);
1030         longPieces.sort(cmpLenRev);
1031         mixedPieces.sort(cmpLenRev);
1032         for (i = 0; i < 12; i++) {
1033             shortPieces[i] = regexEscape(shortPieces[i]);
1034             longPieces[i] = regexEscape(longPieces[i]);
1035         }
1036         for (i = 0; i < 24; i++) {
1037             mixedPieces[i] = regexEscape(mixedPieces[i]);
1038         }
1039
1040         this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1041         this._monthsShortRegex = this._monthsRegex;
1042         this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1043         this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
1044     }
1045
1046     // FORMATTING
1047
1048     addFormatToken('Y', 0, 0, function () {
1049         var y = this.year();
1050         return y <= 9999 ? '' + y : '+' + y;
1051     });
1052
1053     addFormatToken(0, ['YY', 2], 0, function () {
1054         return this.year() % 100;
1055     });
1056
1057     addFormatToken(0, ['YYYY',   4],       0, 'year');
1058     addFormatToken(0, ['YYYYY',  5],       0, 'year');
1059     addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
1060
1061     // ALIASES
1062
1063     addUnitAlias('year', 'y');
1064
1065     // PRIORITIES
1066
1067     addUnitPriority('year', 1);
1068
1069     // PARSING
1070
1071     addRegexToken('Y',      matchSigned);
1072     addRegexToken('YY',     match1to2, match2);
1073     addRegexToken('YYYY',   match1to4, match4);
1074     addRegexToken('YYYYY',  match1to6, match6);
1075     addRegexToken('YYYYYY', match1to6, match6);
1076
1077     addParseToken(['YYYYY', 'YYYYYY'], YEAR);
1078     addParseToken('YYYY', function (input, array) {
1079         array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
1080     });
1081     addParseToken('YY', function (input, array) {
1082         array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
1083     });
1084     addParseToken('Y', function (input, array) {
1085         array[YEAR] = parseInt(input, 10);
1086     });
1087
1088     // HELPERS
1089
1090     function daysInYear(year) {
1091         return isLeapYear(year) ? 366 : 365;
1092     }
1093
1094     function isLeapYear(year) {
1095         return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
1096     }
1097
1098     // HOOKS
1099
1100     utils_hooks__hooks.parseTwoDigitYear = function (input) {
1101         return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
1102     };
1103
1104     // MOMENTS
1105
1106     var getSetYear = makeGetSet('FullYear', true);
1107
1108     function getIsLeapYear () {
1109         return isLeapYear(this.year());
1110     }
1111
1112     function createDate (y, m, d, h, M, s, ms) {
1113         //can't just apply() to create a date:
1114         //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1115         var date = new Date(y, m, d, h, M, s, ms);
1116
1117         //the date constructor remaps years 0-99 to 1900-1999
1118         if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
1119             date.setFullYear(y);
1120         }
1121         return date;
1122     }
1123
1124     function createUTCDate (y) {
1125         var date = new Date(Date.UTC.apply(null, arguments));
1126
1127         //the Date.UTC function remaps years 0-99 to 1900-1999
1128         if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
1129             date.setUTCFullYear(y);
1130         }
1131         return date;
1132     }
1133
1134     // start-of-first-week - start-of-year
1135     function firstWeekOffset(year, dow, doy) {
1136         var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
1137             fwd = 7 + dow - doy,
1138             // first-week day local weekday -- which local weekday is fwd
1139             fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
1140
1141         return -fwdlw + fwd - 1;
1142     }
1143
1144     //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1145     function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
1146         var localWeekday = (7 + weekday - dow) % 7,
1147             weekOffset = firstWeekOffset(year, dow, doy),
1148             dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
1149             resYear, resDayOfYear;
1150
1151         if (dayOfYear <= 0) {
1152             resYear = year - 1;
1153             resDayOfYear = daysInYear(resYear) + dayOfYear;
1154         } else if (dayOfYear > daysInYear(year)) {
1155             resYear = year + 1;
1156             resDayOfYear = dayOfYear - daysInYear(year);
1157         } else {
1158             resYear = year;
1159             resDayOfYear = dayOfYear;
1160         }
1161
1162         return {
1163             year: resYear,
1164             dayOfYear: resDayOfYear
1165         };
1166     }
1167
1168     function weekOfYear(mom, dow, doy) {
1169         var weekOffset = firstWeekOffset(mom.year(), dow, doy),
1170             week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
1171             resWeek, resYear;
1172
1173         if (week < 1) {
1174             resYear = mom.year() - 1;
1175             resWeek = week + weeksInYear(resYear, dow, doy);
1176         } else if (week > weeksInYear(mom.year(), dow, doy)) {
1177             resWeek = week - weeksInYear(mom.year(), dow, doy);
1178             resYear = mom.year() + 1;
1179         } else {
1180             resYear = mom.year();
1181             resWeek = week;
1182         }
1183
1184         return {
1185             week: resWeek,
1186             year: resYear
1187         };
1188     }
1189
1190     function weeksInYear(year, dow, doy) {
1191         var weekOffset = firstWeekOffset(year, dow, doy),
1192             weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
1193         return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
1194     }
1195
1196     // FORMATTING
1197
1198     addFormatToken('w', ['ww', 2], 'wo', 'week');
1199     addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
1200
1201     // ALIASES
1202
1203     addUnitAlias('week', 'w');
1204     addUnitAlias('isoWeek', 'W');
1205
1206     // PRIORITIES
1207
1208     addUnitPriority('week', 5);
1209     addUnitPriority('isoWeek', 5);
1210
1211     // PARSING
1212
1213     addRegexToken('w',  match1to2);
1214     addRegexToken('ww', match1to2, match2);
1215     addRegexToken('W',  match1to2);
1216     addRegexToken('WW', match1to2, match2);
1217
1218     addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
1219         week[token.substr(0, 1)] = toInt(input);
1220     });
1221
1222     // HELPERS
1223
1224     // LOCALES
1225
1226     function localeWeek (mom) {
1227         return weekOfYear(mom, this._week.dow, this._week.doy).week;
1228     }
1229
1230     var defaultLocaleWeek = {
1231         dow : 0, // Sunday is the first day of the week.
1232         doy : 6  // The week that contains Jan 1st is the first week of the year.
1233     };
1234
1235     function localeFirstDayOfWeek () {
1236         return this._week.dow;
1237     }
1238
1239     function localeFirstDayOfYear () {
1240         return this._week.doy;
1241     }
1242
1243     // MOMENTS
1244
1245     function getSetWeek (input) {
1246         var week = this.localeData().week(this);
1247         return input == null ? week : this.add((input - week) * 7, 'd');
1248     }
1249
1250     function getSetISOWeek (input) {
1251         var week = weekOfYear(this, 1, 4).week;
1252         return input == null ? week : this.add((input - week) * 7, 'd');
1253     }
1254
1255     // FORMATTING
1256
1257     addFormatToken('d', 0, 'do', 'day');
1258
1259     addFormatToken('dd', 0, 0, function (format) {
1260         return this.localeData().weekdaysMin(this, format);
1261     });
1262
1263     addFormatToken('ddd', 0, 0, function (format) {
1264         return this.localeData().weekdaysShort(this, format);
1265     });
1266
1267     addFormatToken('dddd', 0, 0, function (format) {
1268         return this.localeData().weekdays(this, format);
1269     });
1270
1271     addFormatToken('e', 0, 0, 'weekday');
1272     addFormatToken('E', 0, 0, 'isoWeekday');
1273
1274     // ALIASES
1275
1276     addUnitAlias('day', 'd');
1277     addUnitAlias('weekday', 'e');
1278     addUnitAlias('isoWeekday', 'E');
1279
1280     // PRIORITY
1281     addUnitPriority('day', 11);
1282     addUnitPriority('weekday', 11);
1283     addUnitPriority('isoWeekday', 11);
1284
1285     // PARSING
1286
1287     addRegexToken('d',    match1to2);
1288     addRegexToken('e',    match1to2);
1289     addRegexToken('E',    match1to2);
1290     addRegexToken('dd',   function (isStrict, locale) {
1291         return locale.weekdaysMinRegex(isStrict);
1292     });
1293     addRegexToken('ddd',   function (isStrict, locale) {
1294         return locale.weekdaysShortRegex(isStrict);
1295     });
1296     addRegexToken('dddd',   function (isStrict, locale) {
1297         return locale.weekdaysRegex(isStrict);
1298     });
1299
1300     addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
1301         var weekday = config._locale.weekdaysParse(input, token, config._strict);
1302         // if we didn't get a weekday name, mark the date as invalid
1303         if (weekday != null) {
1304             week.d = weekday;
1305         } else {
1306             getParsingFlags(config).invalidWeekday = input;
1307         }
1308     });
1309
1310     addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
1311         week[token] = toInt(input);
1312     });
1313
1314     // HELPERS
1315
1316     function parseWeekday(input, locale) {
1317         if (typeof input !== 'string') {
1318             return input;
1319         }
1320
1321         if (!isNaN(input)) {
1322             return parseInt(input, 10);
1323         }
1324
1325         input = locale.weekdaysParse(input);
1326         if (typeof input === 'number') {
1327             return input;
1328         }
1329
1330         return null;
1331     }
1332
1333     function parseIsoWeekday(input, locale) {
1334         if (typeof input === 'string') {
1335             return locale.weekdaysParse(input) % 7 || 7;
1336         }
1337         return isNaN(input) ? null : input;
1338     }
1339
1340     // LOCALES
1341
1342     var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
1343     function localeWeekdays (m, format) {
1344         if (!m) {
1345             return this._weekdays;
1346         }
1347         return isArray(this._weekdays) ? this._weekdays[m.day()] :
1348             this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
1349     }
1350
1351     var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
1352     function localeWeekdaysShort (m) {
1353         return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
1354     }
1355
1356     var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
1357     function localeWeekdaysMin (m) {
1358         return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
1359     }
1360
1361     function day_of_week__handleStrictParse(weekdayName, format, strict) {
1362         var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
1363         if (!this._weekdaysParse) {
1364             this._weekdaysParse = [];
1365             this._shortWeekdaysParse = [];
1366             this._minWeekdaysParse = [];
1367
1368             for (i = 0; i < 7; ++i) {
1369                 mom = create_utc__createUTC([2000, 1]).day(i);
1370                 this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
1371                 this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
1372                 this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
1373             }
1374         }
1375
1376         if (strict) {
1377             if (format === 'dddd') {
1378                 ii = indexOf.call(this._weekdaysParse, llc);
1379                 return ii !== -1 ? ii : null;
1380             } else if (format === 'ddd') {
1381                 ii = indexOf.call(this._shortWeekdaysParse, llc);
1382                 return ii !== -1 ? ii : null;
1383             } else {
1384                 ii = indexOf.call(this._minWeekdaysParse, llc);
1385                 return ii !== -1 ? ii : null;
1386             }
1387         } else {
1388             if (format === 'dddd') {
1389                 ii = indexOf.call(this._weekdaysParse, llc);
1390                 if (ii !== -1) {
1391                     return ii;
1392                 }
1393                 ii = indexOf.call(this._shortWeekdaysParse, llc);
1394                 if (ii !== -1) {
1395                     return ii;
1396                 }
1397                 ii = indexOf.call(this._minWeekdaysParse, llc);
1398                 return ii !== -1 ? ii : null;
1399             } else if (format === 'ddd') {
1400                 ii = indexOf.call(this._shortWeekdaysParse, llc);
1401                 if (ii !== -1) {
1402                     return ii;
1403                 }
1404                 ii = indexOf.call(this._weekdaysParse, llc);
1405                 if (ii !== -1) {
1406                     return ii;
1407                 }
1408                 ii = indexOf.call(this._minWeekdaysParse, llc);
1409                 return ii !== -1 ? ii : null;
1410             } else {
1411                 ii = indexOf.call(this._minWeekdaysParse, llc);
1412                 if (ii !== -1) {
1413                     return ii;
1414                 }
1415                 ii = indexOf.call(this._weekdaysParse, llc);
1416                 if (ii !== -1) {
1417                     return ii;
1418                 }
1419                 ii = indexOf.call(this._shortWeekdaysParse, llc);
1420                 return ii !== -1 ? ii : null;
1421             }
1422         }
1423     }
1424
1425     function localeWeekdaysParse (weekdayName, format, strict) {
1426         var i, mom, regex;
1427
1428         if (this._weekdaysParseExact) {
1429             return day_of_week__handleStrictParse.call(this, weekdayName, format, strict);
1430         }
1431
1432         if (!this._weekdaysParse) {
1433             this._weekdaysParse = [];
1434             this._minWeekdaysParse = [];
1435             this._shortWeekdaysParse = [];
1436             this._fullWeekdaysParse = [];
1437         }
1438
1439         for (i = 0; i < 7; i++) {
1440             // make the regex if we don't have it already
1441
1442             mom = create_utc__createUTC([2000, 1]).day(i);
1443             if (strict && !this._fullWeekdaysParse[i]) {
1444                 this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
1445                 this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
1446                 this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
1447             }
1448             if (!this._weekdaysParse[i]) {
1449                 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
1450                 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
1451             }
1452             // test the regex
1453             if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
1454                 return i;
1455             } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
1456                 return i;
1457             } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
1458                 return i;
1459             } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
1460                 return i;
1461             }
1462         }
1463     }
1464
1465     // MOMENTS
1466
1467     function getSetDayOfWeek (input) {
1468         if (!this.isValid()) {
1469             return input != null ? this : NaN;
1470         }
1471         var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1472         if (input != null) {
1473             input = parseWeekday(input, this.localeData());
1474             return this.add(input - day, 'd');
1475         } else {
1476             return day;
1477         }
1478     }
1479
1480     function getSetLocaleDayOfWeek (input) {
1481         if (!this.isValid()) {
1482             return input != null ? this : NaN;
1483         }
1484         var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
1485         return input == null ? weekday : this.add(input - weekday, 'd');
1486     }
1487
1488     function getSetISODayOfWeek (input) {
1489         if (!this.isValid()) {
1490             return input != null ? this : NaN;
1491         }
1492
1493         // behaves the same as moment#day except
1494         // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
1495         // as a setter, sunday should belong to the previous week.
1496
1497         if (input != null) {
1498             var weekday = parseIsoWeekday(input, this.localeData());
1499             return this.day(this.day() % 7 ? weekday : weekday - 7);
1500         } else {
1501             return this.day() || 7;
1502         }
1503     }
1504
1505     var defaultWeekdaysRegex = matchWord;
1506     function weekdaysRegex (isStrict) {
1507         if (this._weekdaysParseExact) {
1508             if (!hasOwnProp(this, '_weekdaysRegex')) {
1509                 computeWeekdaysParse.call(this);
1510             }
1511             if (isStrict) {
1512                 return this._weekdaysStrictRegex;
1513             } else {
1514                 return this._weekdaysRegex;
1515             }
1516         } else {
1517             if (!hasOwnProp(this, '_weekdaysRegex')) {
1518                 this._weekdaysRegex = defaultWeekdaysRegex;
1519             }
1520             return this._weekdaysStrictRegex && isStrict ?
1521                 this._weekdaysStrictRegex : this._weekdaysRegex;
1522         }
1523     }
1524
1525     var defaultWeekdaysShortRegex = matchWord;
1526     function weekdaysShortRegex (isStrict) {
1527         if (this._weekdaysParseExact) {
1528             if (!hasOwnProp(this, '_weekdaysRegex')) {
1529                 computeWeekdaysParse.call(this);
1530             }
1531             if (isStrict) {
1532                 return this._weekdaysShortStrictRegex;
1533             } else {
1534                 return this._weekdaysShortRegex;
1535             }
1536         } else {
1537             if (!hasOwnProp(this, '_weekdaysShortRegex')) {
1538                 this._weekdaysShortRegex = defaultWeekdaysShortRegex;
1539             }
1540             return this._weekdaysShortStrictRegex && isStrict ?
1541                 this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
1542         }
1543     }
1544
1545     var defaultWeekdaysMinRegex = matchWord;
1546     function weekdaysMinRegex (isStrict) {
1547         if (this._weekdaysParseExact) {
1548             if (!hasOwnProp(this, '_weekdaysRegex')) {
1549                 computeWeekdaysParse.call(this);
1550             }
1551             if (isStrict) {
1552                 return this._weekdaysMinStrictRegex;
1553             } else {
1554                 return this._weekdaysMinRegex;
1555             }
1556         } else {
1557             if (!hasOwnProp(this, '_weekdaysMinRegex')) {
1558                 this._weekdaysMinRegex = defaultWeekdaysMinRegex;
1559             }
1560             return this._weekdaysMinStrictRegex && isStrict ?
1561                 this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
1562         }
1563     }
1564
1565
1566     function computeWeekdaysParse () {
1567         function cmpLenRev(a, b) {
1568             return b.length - a.length;
1569         }
1570
1571         var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
1572             i, mom, minp, shortp, longp;
1573         for (i = 0; i < 7; i++) {
1574             // make the regex if we don't have it already
1575             mom = create_utc__createUTC([2000, 1]).day(i);
1576             minp = this.weekdaysMin(mom, '');
1577             shortp = this.weekdaysShort(mom, '');
1578             longp = this.weekdays(mom, '');
1579             minPieces.push(minp);
1580             shortPieces.push(shortp);
1581             longPieces.push(longp);
1582             mixedPieces.push(minp);
1583             mixedPieces.push(shortp);
1584             mixedPieces.push(longp);
1585         }
1586         // Sorting makes sure if one weekday (or abbr) is a prefix of another it
1587         // will match the longer piece.
1588         minPieces.sort(cmpLenRev);
1589         shortPieces.sort(cmpLenRev);
1590         longPieces.sort(cmpLenRev);
1591         mixedPieces.sort(cmpLenRev);
1592         for (i = 0; i < 7; i++) {
1593             shortPieces[i] = regexEscape(shortPieces[i]);
1594             longPieces[i] = regexEscape(longPieces[i]);
1595             mixedPieces[i] = regexEscape(mixedPieces[i]);
1596         }
1597
1598         this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1599         this._weekdaysShortRegex = this._weekdaysRegex;
1600         this._weekdaysMinRegex = this._weekdaysRegex;
1601
1602         this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1603         this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
1604         this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
1605     }
1606
1607     // FORMATTING
1608
1609     function hFormat() {
1610         return this.hours() % 12 || 12;
1611     }
1612
1613     function kFormat() {
1614         return this.hours() || 24;
1615     }
1616
1617     addFormatToken('H', ['HH', 2], 0, 'hour');
1618     addFormatToken('h', ['hh', 2], 0, hFormat);
1619     addFormatToken('k', ['kk', 2], 0, kFormat);
1620
1621     addFormatToken('hmm', 0, 0, function () {
1622         return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
1623     });
1624
1625     addFormatToken('hmmss', 0, 0, function () {
1626         return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
1627             zeroFill(this.seconds(), 2);
1628     });
1629
1630     addFormatToken('Hmm', 0, 0, function () {
1631         return '' + this.hours() + zeroFill(this.minutes(), 2);
1632     });
1633
1634     addFormatToken('Hmmss', 0, 0, function () {
1635         return '' + this.hours() + zeroFill(this.minutes(), 2) +
1636             zeroFill(this.seconds(), 2);
1637     });
1638
1639     function meridiem (token, lowercase) {
1640         addFormatToken(token, 0, 0, function () {
1641             return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
1642         });
1643     }
1644
1645     meridiem('a', true);
1646     meridiem('A', false);
1647
1648     // ALIASES
1649
1650     addUnitAlias('hour', 'h');
1651
1652     // PRIORITY
1653     addUnitPriority('hour', 13);
1654
1655     // PARSING
1656
1657     function matchMeridiem (isStrict, locale) {
1658         return locale._meridiemParse;
1659     }
1660
1661     addRegexToken('a',  matchMeridiem);
1662     addRegexToken('A',  matchMeridiem);
1663     addRegexToken('H',  match1to2);
1664     addRegexToken('h',  match1to2);
1665     addRegexToken('HH', match1to2, match2);
1666     addRegexToken('hh', match1to2, match2);
1667
1668     addRegexToken('hmm', match3to4);
1669     addRegexToken('hmmss', match5to6);
1670     addRegexToken('Hmm', match3to4);
1671     addRegexToken('Hmmss', match5to6);
1672
1673     addParseToken(['H', 'HH'], HOUR);
1674     addParseToken(['a', 'A'], function (input, array, config) {
1675         config._isPm = config._locale.isPM(input);
1676         config._meridiem = input;
1677     });
1678     addParseToken(['h', 'hh'], function (input, array, config) {
1679         array[HOUR] = toInt(input);
1680         getParsingFlags(config).bigHour = true;
1681     });
1682     addParseToken('hmm', function (input, array, config) {
1683         var pos = input.length - 2;
1684         array[HOUR] = toInt(input.substr(0, pos));
1685         array[MINUTE] = toInt(input.substr(pos));
1686         getParsingFlags(config).bigHour = true;
1687     });
1688     addParseToken('hmmss', function (input, array, config) {
1689         var pos1 = input.length - 4;
1690         var pos2 = input.length - 2;
1691         array[HOUR] = toInt(input.substr(0, pos1));
1692         array[MINUTE] = toInt(input.substr(pos1, 2));
1693         array[SECOND] = toInt(input.substr(pos2));
1694         getParsingFlags(config).bigHour = true;
1695     });
1696     addParseToken('Hmm', function (input, array, config) {
1697         var pos = input.length - 2;
1698         array[HOUR] = toInt(input.substr(0, pos));
1699         array[MINUTE] = toInt(input.substr(pos));
1700     });
1701     addParseToken('Hmmss', function (input, array, config) {
1702         var pos1 = input.length - 4;
1703         var pos2 = input.length - 2;
1704         array[HOUR] = toInt(input.substr(0, pos1));
1705         array[MINUTE] = toInt(input.substr(pos1, 2));
1706         array[SECOND] = toInt(input.substr(pos2));
1707     });
1708
1709     // LOCALES
1710
1711     function localeIsPM (input) {
1712         // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
1713         // Using charAt should be more compatible.
1714         return ((input + '').toLowerCase().charAt(0) === 'p');
1715     }
1716
1717     var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
1718     function localeMeridiem (hours, minutes, isLower) {
1719         if (hours > 11) {
1720             return isLower ? 'pm' : 'PM';
1721         } else {
1722             return isLower ? 'am' : 'AM';
1723         }
1724     }
1725
1726
1727     // MOMENTS
1728
1729     // Setting the hour should keep the time, because the user explicitly
1730     // specified which hour he wants. So trying to maintain the same hour (in
1731     // a new timezone) makes sense. Adding/subtracting hours does not follow
1732     // this rule.
1733     var getSetHour = makeGetSet('Hours', true);
1734
1735     var baseConfig = {
1736         calendar: defaultCalendar,
1737         longDateFormat: defaultLongDateFormat,
1738         invalidDate: defaultInvalidDate,
1739         ordinal: defaultOrdinal,
1740         ordinalParse: defaultOrdinalParse,
1741         relativeTime: defaultRelativeTime,
1742
1743         months: defaultLocaleMonths,
1744         monthsShort: defaultLocaleMonthsShort,
1745
1746         week: defaultLocaleWeek,
1747
1748         weekdays: defaultLocaleWeekdays,
1749         weekdaysMin: defaultLocaleWeekdaysMin,
1750         weekdaysShort: defaultLocaleWeekdaysShort,
1751
1752         meridiemParse: defaultLocaleMeridiemParse
1753     };
1754
1755     // internal storage for locale config files
1756     var locales = {};
1757     var globalLocale;
1758
1759     function normalizeLocale(key) {
1760         return key ? key.toLowerCase().replace('_', '-') : key;
1761     }
1762
1763     // pick the locale from the array
1764     // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
1765     // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
1766     function chooseLocale(names) {
1767         var i = 0, j, next, locale, split;
1768
1769         while (i < names.length) {
1770             split = normalizeLocale(names[i]).split('-');
1771             j = split.length;
1772             next = normalizeLocale(names[i + 1]);
1773             next = next ? next.split('-') : null;
1774             while (j > 0) {
1775                 locale = loadLocale(split.slice(0, j).join('-'));
1776                 if (locale) {
1777                     return locale;
1778                 }
1779                 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
1780                     //the next array item is better than a shallower substring of this one
1781                     break;
1782                 }
1783                 j--;
1784             }
1785             i++;
1786         }
1787         return null;
1788     }
1789
1790     function loadLocale(name) {
1791         var oldLocale = null;
1792         // TODO: Find a better way to register and load all the locales in Node
1793         if (!locales[name] && (typeof module !== 'undefined') &&
1794                 module && module.exports) {
1795             try {
1796                 oldLocale = globalLocale._abbr;
1797                 require('./locale/' + name);
1798                 // because defineLocale currently also sets the global locale, we
1799                 // want to undo that for lazy loaded locales
1800                 locale_locales__getSetGlobalLocale(oldLocale);
1801             } catch (e) { }
1802         }
1803         return locales[name];
1804     }
1805
1806     // This function will load locale and then set the global locale.  If
1807     // no arguments are passed in, it will simply return the current global
1808     // locale key.
1809     function locale_locales__getSetGlobalLocale (key, values) {
1810         var data;
1811         if (key) {
1812             if (isUndefined(values)) {
1813                 data = locale_locales__getLocale(key);
1814             }
1815             else {
1816                 data = defineLocale(key, values);
1817             }
1818
1819             if (data) {
1820                 // moment.duration._locale = moment._locale = data;
1821                 globalLocale = data;
1822             }
1823         }
1824
1825         return globalLocale._abbr;
1826     }
1827
1828     function defineLocale (name, config) {
1829         if (config !== null) {
1830             var parentConfig = baseConfig;
1831             config.abbr = name;
1832             if (locales[name] != null) {
1833                 deprecateSimple('defineLocaleOverride',
1834                         'use moment.updateLocale(localeName, config) to change ' +
1835                         'an existing locale. moment.defineLocale(localeName, ' +
1836                         'config) should only be used for creating a new locale ' +
1837                         'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
1838                 parentConfig = locales[name]._config;
1839             } else if (config.parentLocale != null) {
1840                 if (locales[config.parentLocale] != null) {
1841                     parentConfig = locales[config.parentLocale]._config;
1842                 } else {
1843                     // treat as if there is no base config
1844                     deprecateSimple('parentLocaleUndefined',
1845                             'specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/');
1846                 }
1847             }
1848             locales[name] = new Locale(mergeConfigs(parentConfig, config));
1849
1850             // backwards compat for now: also set the locale
1851             locale_locales__getSetGlobalLocale(name);
1852
1853             return locales[name];
1854         } else {
1855             // useful for testing
1856             delete locales[name];
1857             return null;
1858         }
1859     }
1860
1861     function updateLocale(name, config) {
1862         if (config != null) {
1863             var locale, parentConfig = baseConfig;
1864             // MERGE
1865             if (locales[name] != null) {
1866                 parentConfig = locales[name]._config;
1867             }
1868             config = mergeConfigs(parentConfig, config);
1869             locale = new Locale(config);
1870             locale.parentLocale = locales[name];
1871             locales[name] = locale;
1872
1873             // backwards compat for now: also set the locale
1874             locale_locales__getSetGlobalLocale(name);
1875         } else {
1876             // pass null for config to unupdate, useful for tests
1877             if (locales[name] != null) {
1878                 if (locales[name].parentLocale != null) {
1879                     locales[name] = locales[name].parentLocale;
1880                 } else if (locales[name] != null) {
1881                     delete locales[name];
1882                 }
1883             }
1884         }
1885         return locales[name];
1886     }
1887
1888     // returns locale data
1889     function locale_locales__getLocale (key) {
1890         var locale;
1891
1892         if (key && key._locale && key._locale._abbr) {
1893             key = key._locale._abbr;
1894         }
1895
1896         if (!key) {
1897             return globalLocale;
1898         }
1899
1900         if (!isArray(key)) {
1901             //short-circuit everything else
1902             locale = loadLocale(key);
1903             if (locale) {
1904                 return locale;
1905             }
1906             key = [key];
1907         }
1908
1909         return chooseLocale(key);
1910     }
1911
1912     function locale_locales__listLocales() {
1913         return keys(locales);
1914     }
1915
1916     function checkOverflow (m) {
1917         var overflow;
1918         var a = m._a;
1919
1920         if (a && getParsingFlags(m).overflow === -2) {
1921             overflow =
1922                 a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
1923                 a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
1924                 a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
1925                 a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
1926                 a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
1927                 a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
1928                 -1;
1929
1930             if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
1931                 overflow = DATE;
1932             }
1933             if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
1934                 overflow = WEEK;
1935             }
1936             if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
1937                 overflow = WEEKDAY;
1938             }
1939
1940             getParsingFlags(m).overflow = overflow;
1941         }
1942
1943         return m;
1944     }
1945
1946     // iso 8601 regex
1947     // 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)
1948     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)?)?/;
1949     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)?)?/;
1950
1951     var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
1952
1953     var isoDates = [
1954         ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
1955         ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
1956         ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
1957         ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
1958         ['YYYY-DDD', /\d{4}-\d{3}/],
1959         ['YYYY-MM', /\d{4}-\d\d/, false],
1960         ['YYYYYYMMDD', /[+-]\d{10}/],
1961         ['YYYYMMDD', /\d{8}/],
1962         // YYYYMM is NOT allowed by the standard
1963         ['GGGG[W]WWE', /\d{4}W\d{3}/],
1964         ['GGGG[W]WW', /\d{4}W\d{2}/, false],
1965         ['YYYYDDD', /\d{7}/]
1966     ];
1967
1968     // iso time formats and regexes
1969     var isoTimes = [
1970         ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
1971         ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
1972         ['HH:mm:ss', /\d\d:\d\d:\d\d/],
1973         ['HH:mm', /\d\d:\d\d/],
1974         ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
1975         ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
1976         ['HHmmss', /\d\d\d\d\d\d/],
1977         ['HHmm', /\d\d\d\d/],
1978         ['HH', /\d\d/]
1979     ];
1980
1981     var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
1982
1983     // date from iso format
1984     function configFromISO(config) {
1985         var i, l,
1986             string = config._i,
1987             match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
1988             allowTime, dateFormat, timeFormat, tzFormat;
1989
1990         if (match) {
1991             getParsingFlags(config).iso = true;
1992
1993             for (i = 0, l = isoDates.length; i < l; i++) {
1994                 if (isoDates[i][1].exec(match[1])) {
1995                     dateFormat = isoDates[i][0];
1996                     allowTime = isoDates[i][2] !== false;
1997                     break;
1998                 }
1999             }
2000             if (dateFormat == null) {
2001                 config._isValid = false;
2002                 return;
2003             }
2004             if (match[3]) {
2005                 for (i = 0, l = isoTimes.length; i < l; i++) {
2006                     if (isoTimes[i][1].exec(match[3])) {
2007                         // match[2] should be 'T' or space
2008                         timeFormat = (match[2] || ' ') + isoTimes[i][0];
2009                         break;
2010                     }
2011                 }
2012                 if (timeFormat == null) {
2013                     config._isValid = false;
2014                     return;
2015                 }
2016             }
2017             if (!allowTime && timeFormat != null) {
2018                 config._isValid = false;
2019                 return;
2020             }
2021             if (match[4]) {
2022                 if (tzRegex.exec(match[4])) {
2023                     tzFormat = 'Z';
2024                 } else {
2025                     config._isValid = false;
2026                     return;
2027                 }
2028             }
2029             config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
2030             configFromStringAndFormat(config);
2031         } else {
2032             config._isValid = false;
2033         }
2034     }
2035
2036     // date from iso format or fallback
2037     function configFromString(config) {
2038         var matched = aspNetJsonRegex.exec(config._i);
2039
2040         if (matched !== null) {
2041             config._d = new Date(+matched[1]);
2042             return;
2043         }
2044
2045         configFromISO(config);
2046         if (config._isValid === false) {
2047             delete config._isValid;
2048             utils_hooks__hooks.createFromInputFallback(config);
2049         }
2050     }
2051
2052     utils_hooks__hooks.createFromInputFallback = deprecate(
2053         'value provided is not in a recognized ISO format. moment construction falls back to js Date(), ' +
2054         'which is not reliable across all browsers and versions. Non ISO date formats are ' +
2055         'discouraged and will be removed in an upcoming major release. Please refer to ' +
2056         'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
2057         function (config) {
2058             config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
2059         }
2060     );
2061
2062     // Pick the first defined of two or three arguments.
2063     function defaults(a, b, c) {
2064         if (a != null) {
2065             return a;
2066         }
2067         if (b != null) {
2068             return b;
2069         }
2070         return c;
2071     }
2072
2073     function currentDateArray(config) {
2074         // hooks is actually the exported moment object
2075         var nowValue = new Date(utils_hooks__hooks.now());
2076         if (config._useUTC) {
2077             return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
2078         }
2079         return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
2080     }
2081
2082     // convert an array to a date.
2083     // the array should mirror the parameters below
2084     // note: all values past the year are optional and will default to the lowest possible value.
2085     // [year, month, day , hour, minute, second, millisecond]
2086     function configFromArray (config) {
2087         var i, date, input = [], currentDate, yearToUse;
2088
2089         if (config._d) {
2090             return;
2091         }
2092
2093         currentDate = currentDateArray(config);
2094
2095         //compute day of the year from weeks and weekdays
2096         if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
2097             dayOfYearFromWeekInfo(config);
2098         }
2099
2100         //if the day of the year is set, figure out what it is
2101         if (config._dayOfYear) {
2102             yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
2103
2104             if (config._dayOfYear > daysInYear(yearToUse)) {
2105                 getParsingFlags(config)._overflowDayOfYear = true;
2106             }
2107
2108             date = createUTCDate(yearToUse, 0, config._dayOfYear);
2109             config._a[MONTH] = date.getUTCMonth();
2110             config._a[DATE] = date.getUTCDate();
2111         }
2112
2113         // Default to current date.
2114         // * if no year, month, day of month are given, default to today
2115         // * if day of month is given, default month and year
2116         // * if month is given, default only year
2117         // * if year is given, don't default anything
2118         for (i = 0; i < 3 && config._a[i] == null; ++i) {
2119             config._a[i] = input[i] = currentDate[i];
2120         }
2121
2122         // Zero out whatever was not defaulted, including time
2123         for (; i < 7; i++) {
2124             config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
2125         }
2126
2127         // Check for 24:00:00.000
2128         if (config._a[HOUR] === 24 &&
2129                 config._a[MINUTE] === 0 &&
2130                 config._a[SECOND] === 0 &&
2131                 config._a[MILLISECOND] === 0) {
2132             config._nextDay = true;
2133             config._a[HOUR] = 0;
2134         }
2135
2136         config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
2137         // Apply timezone offset from input. The actual utcOffset can be changed
2138         // with parseZone.
2139         if (config._tzm != null) {
2140             config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
2141         }
2142
2143         if (config._nextDay) {
2144             config._a[HOUR] = 24;
2145         }
2146     }
2147
2148     function dayOfYearFromWeekInfo(config) {
2149         var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
2150
2151         w = config._w;
2152         if (w.GG != null || w.W != null || w.E != null) {
2153             dow = 1;
2154             doy = 4;
2155
2156             // TODO: We need to take the current isoWeekYear, but that depends on
2157             // how we interpret now (local, utc, fixed offset). So create
2158             // a now version of current config (take local/utc/offset flags, and
2159             // create now).
2160             weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
2161             week = defaults(w.W, 1);
2162             weekday = defaults(w.E, 1);
2163             if (weekday < 1 || weekday > 7) {
2164                 weekdayOverflow = true;
2165             }
2166         } else {
2167             dow = config._locale._week.dow;
2168             doy = config._locale._week.doy;
2169
2170             weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
2171             week = defaults(w.w, 1);
2172
2173             if (w.d != null) {
2174                 // weekday -- low day numbers are considered next week
2175                 weekday = w.d;
2176                 if (weekday < 0 || weekday > 6) {
2177                     weekdayOverflow = true;
2178                 }
2179             } else if (w.e != null) {
2180                 // local weekday -- counting starts from begining of week
2181                 weekday = w.e + dow;
2182                 if (w.e < 0 || w.e > 6) {
2183                     weekdayOverflow = true;
2184                 }
2185             } else {
2186                 // default to begining of week
2187                 weekday = dow;
2188             }
2189         }
2190         if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
2191             getParsingFlags(config)._overflowWeeks = true;
2192         } else if (weekdayOverflow != null) {
2193             getParsingFlags(config)._overflowWeekday = true;
2194         } else {
2195             temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
2196             config._a[YEAR] = temp.year;
2197             config._dayOfYear = temp.dayOfYear;
2198         }
2199     }
2200
2201     // constant that refers to the ISO standard
2202     utils_hooks__hooks.ISO_8601 = function () {};
2203
2204     // date from string and format string
2205     function configFromStringAndFormat(config) {
2206         // TODO: Move this to another part of the creation flow to prevent circular deps
2207         if (config._f === utils_hooks__hooks.ISO_8601) {
2208             configFromISO(config);
2209             return;
2210         }
2211
2212         config._a = [];
2213         getParsingFlags(config).empty = true;
2214
2215         // This array is used to make a Date, either with `new Date` or `Date.UTC`
2216         var string = '' + config._i,
2217             i, parsedInput, tokens, token, skipped,
2218             stringLength = string.length,
2219             totalParsedInputLength = 0;
2220
2221         tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
2222
2223         for (i = 0; i < tokens.length; i++) {
2224             token = tokens[i];
2225             parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
2226             // console.log('token', token, 'parsedInput', parsedInput,
2227             //         'regex', getParseRegexForToken(token, config));
2228             if (parsedInput) {
2229                 skipped = string.substr(0, string.indexOf(parsedInput));
2230                 if (skipped.length > 0) {
2231                     getParsingFlags(config).unusedInput.push(skipped);
2232                 }
2233                 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
2234                 totalParsedInputLength += parsedInput.length;
2235             }
2236             // don't parse if it's not a known token
2237             if (formatTokenFunctions[token]) {
2238                 if (parsedInput) {
2239                     getParsingFlags(config).empty = false;
2240                 }
2241                 else {
2242                     getParsingFlags(config).unusedTokens.push(token);
2243                 }
2244                 addTimeToArrayFromToken(token, parsedInput, config);
2245             }
2246             else if (config._strict && !parsedInput) {
2247                 getParsingFlags(config).unusedTokens.push(token);
2248             }
2249         }
2250
2251         // add remaining unparsed input length to the string
2252         getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
2253         if (string.length > 0) {
2254             getParsingFlags(config).unusedInput.push(string);
2255         }
2256
2257         // clear _12h flag if hour is <= 12
2258         if (config._a[HOUR] <= 12 &&
2259             getParsingFlags(config).bigHour === true &&
2260             config._a[HOUR] > 0) {
2261             getParsingFlags(config).bigHour = undefined;
2262         }
2263
2264         getParsingFlags(config).parsedDateParts = config._a.slice(0);
2265         getParsingFlags(config).meridiem = config._meridiem;
2266         // handle meridiem
2267         config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
2268
2269         configFromArray(config);
2270         checkOverflow(config);
2271     }
2272
2273
2274     function meridiemFixWrap (locale, hour, meridiem) {
2275         var isPm;
2276
2277         if (meridiem == null) {
2278             // nothing to do
2279             return hour;
2280         }
2281         if (locale.meridiemHour != null) {
2282             return locale.meridiemHour(hour, meridiem);
2283         } else if (locale.isPM != null) {
2284             // Fallback
2285             isPm = locale.isPM(meridiem);
2286             if (isPm && hour < 12) {
2287                 hour += 12;
2288             }
2289             if (!isPm && hour === 12) {
2290                 hour = 0;
2291             }
2292             return hour;
2293         } else {
2294             // this is not supposed to happen
2295             return hour;
2296         }
2297     }
2298
2299     // date from string and array of format strings
2300     function configFromStringAndArray(config) {
2301         var tempConfig,
2302             bestMoment,
2303
2304             scoreToBeat,
2305             i,
2306             currentScore;
2307
2308         if (config._f.length === 0) {
2309             getParsingFlags(config).invalidFormat = true;
2310             config._d = new Date(NaN);
2311             return;
2312         }
2313
2314         for (i = 0; i < config._f.length; i++) {
2315             currentScore = 0;
2316             tempConfig = copyConfig({}, config);
2317             if (config._useUTC != null) {
2318                 tempConfig._useUTC = config._useUTC;
2319             }
2320             tempConfig._f = config._f[i];
2321             configFromStringAndFormat(tempConfig);
2322
2323             if (!valid__isValid(tempConfig)) {
2324                 continue;
2325             }
2326
2327             // if there is any input that was not parsed add a penalty for that format
2328             currentScore += getParsingFlags(tempConfig).charsLeftOver;
2329
2330             //or tokens
2331             currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
2332
2333             getParsingFlags(tempConfig).score = currentScore;
2334
2335             if (scoreToBeat == null || currentScore < scoreToBeat) {
2336                 scoreToBeat = currentScore;
2337                 bestMoment = tempConfig;
2338             }
2339         }
2340
2341         extend(config, bestMoment || tempConfig);
2342     }
2343
2344     function configFromObject(config) {
2345         if (config._d) {
2346             return;
2347         }
2348
2349         var i = normalizeObjectUnits(config._i);
2350         config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
2351             return obj && parseInt(obj, 10);
2352         });
2353
2354         configFromArray(config);
2355     }
2356
2357     function createFromConfig (config) {
2358         var res = new Moment(checkOverflow(prepareConfig(config)));
2359         if (res._nextDay) {
2360             // Adding is smart enough around DST
2361             res.add(1, 'd');
2362             res._nextDay = undefined;
2363         }
2364
2365         return res;
2366     }
2367
2368     function prepareConfig (config) {
2369         var input = config._i,
2370             format = config._f;
2371
2372         config._locale = config._locale || locale_locales__getLocale(config._l);
2373
2374         if (input === null || (format === undefined && input === '')) {
2375             return valid__createInvalid({nullInput: true});
2376         }
2377
2378         if (typeof input === 'string') {
2379             config._i = input = config._locale.preparse(input);
2380         }
2381
2382         if (isMoment(input)) {
2383             return new Moment(checkOverflow(input));
2384         } else if (isArray(format)) {
2385             configFromStringAndArray(config);
2386         } else if (isDate(input)) {
2387             config._d = input;
2388         } else if (format) {
2389             configFromStringAndFormat(config);
2390         }  else {
2391             configFromInput(config);
2392         }
2393
2394         if (!valid__isValid(config)) {
2395             config._d = null;
2396         }
2397
2398         return config;
2399     }
2400
2401     function configFromInput(config) {
2402         var input = config._i;
2403         if (input === undefined) {
2404             config._d = new Date(utils_hooks__hooks.now());
2405         } else if (isDate(input)) {
2406             config._d = new Date(input.valueOf());
2407         } else if (typeof input === 'string') {
2408             configFromString(config);
2409         } else if (isArray(input)) {
2410             config._a = map(input.slice(0), function (obj) {
2411                 return parseInt(obj, 10);
2412             });
2413             configFromArray(config);
2414         } else if (typeof(input) === 'object') {
2415             configFromObject(config);
2416         } else if (typeof(input) === 'number') {
2417             // from milliseconds
2418             config._d = new Date(input);
2419         } else {
2420             utils_hooks__hooks.createFromInputFallback(config);
2421         }
2422     }
2423
2424     function createLocalOrUTC (input, format, locale, strict, isUTC) {
2425         var c = {};
2426
2427         if (typeof(locale) === 'boolean') {
2428             strict = locale;
2429             locale = undefined;
2430         }
2431
2432         if ((isObject(input) && isObjectEmpty(input)) ||
2433                 (isArray(input) && input.length === 0)) {
2434             input = undefined;
2435         }
2436         // object construction must be done this way.
2437         // https://github.com/moment/moment/issues/1423
2438         c._isAMomentObject = true;
2439         c._useUTC = c._isUTC = isUTC;
2440         c._l = locale;
2441         c._i = input;
2442         c._f = format;
2443         c._strict = strict;
2444
2445         return createFromConfig(c);
2446     }
2447
2448     function local__createLocal (input, format, locale, strict) {
2449         return createLocalOrUTC(input, format, locale, strict, false);
2450     }
2451
2452     var prototypeMin = deprecate(
2453         'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
2454         function () {
2455             var other = local__createLocal.apply(null, arguments);
2456             if (this.isValid() && other.isValid()) {
2457                 return other < this ? this : other;
2458             } else {
2459                 return valid__createInvalid();
2460             }
2461         }
2462     );
2463
2464     var prototypeMax = deprecate(
2465         'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
2466         function () {
2467             var other = local__createLocal.apply(null, arguments);
2468             if (this.isValid() && other.isValid()) {
2469                 return other > this ? this : other;
2470             } else {
2471                 return valid__createInvalid();
2472             }
2473         }
2474     );
2475
2476     // Pick a moment m from moments so that m[fn](other) is true for all
2477     // other. This relies on the function fn to be transitive.
2478     //
2479     // moments should either be an array of moment objects or an array, whose
2480     // first element is an array of moment objects.
2481     function pickBy(fn, moments) {
2482         var res, i;
2483         if (moments.length === 1 && isArray(moments[0])) {
2484             moments = moments[0];
2485         }
2486         if (!moments.length) {
2487             return local__createLocal();
2488         }
2489         res = moments[0];
2490         for (i = 1; i < moments.length; ++i) {
2491             if (!moments[i].isValid() || moments[i][fn](res)) {
2492                 res = moments[i];
2493             }
2494         }
2495         return res;
2496     }
2497
2498     // TODO: Use [].sort instead?
2499     function min () {
2500         var args = [].slice.call(arguments, 0);
2501
2502         return pickBy('isBefore', args);
2503     }
2504
2505     function max () {
2506         var args = [].slice.call(arguments, 0);
2507
2508         return pickBy('isAfter', args);
2509     }
2510
2511     var now = function () {
2512         return Date.now ? Date.now() : +(new Date());
2513     };
2514
2515     function Duration (duration) {
2516         var normalizedInput = normalizeObjectUnits(duration),
2517             years = normalizedInput.year || 0,
2518             quarters = normalizedInput.quarter || 0,
2519             months = normalizedInput.month || 0,
2520             weeks = normalizedInput.week || 0,
2521             days = normalizedInput.day || 0,
2522             hours = normalizedInput.hour || 0,
2523             minutes = normalizedInput.minute || 0,
2524             seconds = normalizedInput.second || 0,
2525             milliseconds = normalizedInput.millisecond || 0;
2526
2527         // representation for dateAddRemove
2528         this._milliseconds = +milliseconds +
2529             seconds * 1e3 + // 1000
2530             minutes * 6e4 + // 1000 * 60
2531             hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
2532         // Because of dateAddRemove treats 24 hours as different from a
2533         // day when working around DST, we need to store them separately
2534         this._days = +days +
2535             weeks * 7;
2536         // It is impossible translate months into days without knowing
2537         // which months you are are talking about, so we have to store
2538         // it separately.
2539         this._months = +months +
2540             quarters * 3 +
2541             years * 12;
2542
2543         this._data = {};
2544
2545         this._locale = locale_locales__getLocale();
2546
2547         this._bubble();
2548     }
2549
2550     function isDuration (obj) {
2551         return obj instanceof Duration;
2552     }
2553
2554     function absRound (number) {
2555         if (number < 0) {
2556             return Math.round(-1 * number) * -1;
2557         } else {
2558             return Math.round(number);
2559         }
2560     }
2561
2562     // FORMATTING
2563
2564     function offset (token, separator) {
2565         addFormatToken(token, 0, 0, function () {
2566             var offset = this.utcOffset();
2567             var sign = '+';
2568             if (offset < 0) {
2569                 offset = -offset;
2570                 sign = '-';
2571             }
2572             return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
2573         });
2574     }
2575
2576     offset('Z', ':');
2577     offset('ZZ', '');
2578
2579     // PARSING
2580
2581     addRegexToken('Z',  matchShortOffset);
2582     addRegexToken('ZZ', matchShortOffset);
2583     addParseToken(['Z', 'ZZ'], function (input, array, config) {
2584         config._useUTC = true;
2585         config._tzm = offsetFromString(matchShortOffset, input);
2586     });
2587
2588     // HELPERS
2589
2590     // timezone chunker
2591     // '+10:00' > ['10',  '00']
2592     // '-1530'  > ['-15', '30']
2593     var chunkOffset = /([\+\-]|\d\d)/gi;
2594
2595     function offsetFromString(matcher, string) {
2596         var matches = ((string || '').match(matcher) || []);
2597         var chunk   = matches[matches.length - 1] || [];
2598         var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
2599         var minutes = +(parts[1] * 60) + toInt(parts[2]);
2600
2601         return parts[0] === '+' ? minutes : -minutes;
2602     }
2603
2604     // Return a moment from input, that is local/utc/zone equivalent to model.
2605     function cloneWithOffset(input, model) {
2606         var res, diff;
2607         if (model._isUTC) {
2608             res = model.clone();
2609             diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
2610             // Use low-level api, because this fn is low-level api.
2611             res._d.setTime(res._d.valueOf() + diff);
2612             utils_hooks__hooks.updateOffset(res, false);
2613             return res;
2614         } else {
2615             return local__createLocal(input).local();
2616         }
2617     }
2618
2619     function getDateOffset (m) {
2620         // On Firefox.24 Date#getTimezoneOffset returns a floating point.
2621         // https://github.com/moment/moment/pull/1871
2622         return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
2623     }
2624
2625     // HOOKS
2626
2627     // This function will be called whenever a moment is mutated.
2628     // It is intended to keep the offset in sync with the timezone.
2629     utils_hooks__hooks.updateOffset = function () {};
2630
2631     // MOMENTS
2632
2633     // keepLocalTime = true means only change the timezone, without
2634     // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
2635     // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
2636     // +0200, so we adjust the time as needed, to be valid.
2637     //
2638     // Keeping the time actually adds/subtracts (one hour)
2639     // from the actual represented time. That is why we call updateOffset
2640     // a second time. In case it wants us to change the offset again
2641     // _changeInProgress == true case, then we have to adjust, because
2642     // there is no such time in the given timezone.
2643     function getSetOffset (input, keepLocalTime) {
2644         var offset = this._offset || 0,
2645             localAdjust;
2646         if (!this.isValid()) {
2647             return input != null ? this : NaN;
2648         }
2649         if (input != null) {
2650             if (typeof input === 'string') {
2651                 input = offsetFromString(matchShortOffset, input);
2652             } else if (Math.abs(input) < 16) {
2653                 input = input * 60;
2654             }
2655             if (!this._isUTC && keepLocalTime) {
2656                 localAdjust = getDateOffset(this);
2657             }
2658             this._offset = input;
2659             this._isUTC = true;
2660             if (localAdjust != null) {
2661                 this.add(localAdjust, 'm');
2662             }
2663             if (offset !== input) {
2664                 if (!keepLocalTime || this._changeInProgress) {
2665                     add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
2666                 } else if (!this._changeInProgress) {
2667                     this._changeInProgress = true;
2668                     utils_hooks__hooks.updateOffset(this, true);
2669                     this._changeInProgress = null;
2670                 }
2671             }
2672             return this;
2673         } else {
2674             return this._isUTC ? offset : getDateOffset(this);
2675         }
2676     }
2677
2678     function getSetZone (input, keepLocalTime) {
2679         if (input != null) {
2680             if (typeof input !== 'string') {
2681                 input = -input;
2682             }
2683
2684             this.utcOffset(input, keepLocalTime);
2685
2686             return this;
2687         } else {
2688             return -this.utcOffset();
2689         }
2690     }
2691
2692     function setOffsetToUTC (keepLocalTime) {
2693         return this.utcOffset(0, keepLocalTime);
2694     }
2695
2696     function setOffsetToLocal (keepLocalTime) {
2697         if (this._isUTC) {
2698             this.utcOffset(0, keepLocalTime);
2699             this._isUTC = false;
2700
2701             if (keepLocalTime) {
2702                 this.subtract(getDateOffset(this), 'm');
2703             }
2704         }
2705         return this;
2706     }
2707
2708     function setOffsetToParsedOffset () {
2709         if (this._tzm) {
2710             this.utcOffset(this._tzm);
2711         } else if (typeof this._i === 'string') {
2712             var tZone = offsetFromString(matchOffset, this._i);
2713
2714             if (tZone === 0) {
2715                 this.utcOffset(0, true);
2716             } else {
2717                 this.utcOffset(offsetFromString(matchOffset, this._i));
2718             }
2719         }
2720         return this;
2721     }
2722
2723     function hasAlignedHourOffset (input) {
2724         if (!this.isValid()) {
2725             return false;
2726         }
2727         input = input ? local__createLocal(input).utcOffset() : 0;
2728
2729         return (this.utcOffset() - input) % 60 === 0;
2730     }
2731
2732     function isDaylightSavingTime () {
2733         return (
2734             this.utcOffset() > this.clone().month(0).utcOffset() ||
2735             this.utcOffset() > this.clone().month(5).utcOffset()
2736         );
2737     }
2738
2739     function isDaylightSavingTimeShifted () {
2740         if (!isUndefined(this._isDSTShifted)) {
2741             return this._isDSTShifted;
2742         }
2743
2744         var c = {};
2745
2746         copyConfig(c, this);
2747         c = prepareConfig(c);
2748
2749         if (c._a) {
2750             var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
2751             this._isDSTShifted = this.isValid() &&
2752                 compareArrays(c._a, other.toArray()) > 0;
2753         } else {
2754             this._isDSTShifted = false;
2755         }
2756
2757         return this._isDSTShifted;
2758     }
2759
2760     function isLocal () {
2761         return this.isValid() ? !this._isUTC : false;
2762     }
2763
2764     function isUtcOffset () {
2765         return this.isValid() ? this._isUTC : false;
2766     }
2767
2768     function isUtc () {
2769         return this.isValid() ? this._isUTC && this._offset === 0 : false;
2770     }
2771
2772     // ASP.NET json date format regex
2773     var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
2774
2775     // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
2776     // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
2777     // and further modified to allow for strings containing both week and day
2778     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)?)?$/;
2779
2780     function create__createDuration (input, key) {
2781         var duration = input,
2782             // matching against regexp is expensive, do it on demand
2783             match = null,
2784             sign,
2785             ret,
2786             diffRes;
2787
2788         if (isDuration(input)) {
2789             duration = {
2790                 ms : input._milliseconds,
2791                 d  : input._days,
2792                 M  : input._months
2793             };
2794         } else if (typeof input === 'number') {
2795             duration = {};
2796             if (key) {
2797                 duration[key] = input;
2798             } else {
2799                 duration.milliseconds = input;
2800             }
2801         } else if (!!(match = aspNetRegex.exec(input))) {
2802             sign = (match[1] === '-') ? -1 : 1;
2803             duration = {
2804                 y  : 0,
2805                 d  : toInt(match[DATE])                         * sign,
2806                 h  : toInt(match[HOUR])                         * sign,
2807                 m  : toInt(match[MINUTE])                       * sign,
2808                 s  : toInt(match[SECOND])                       * sign,
2809                 ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
2810             };
2811         } else if (!!(match = isoRegex.exec(input))) {
2812             sign = (match[1] === '-') ? -1 : 1;
2813             duration = {
2814                 y : parseIso(match[2], sign),
2815                 M : parseIso(match[3], sign),
2816                 w : parseIso(match[4], sign),
2817                 d : parseIso(match[5], sign),
2818                 h : parseIso(match[6], sign),
2819                 m : parseIso(match[7], sign),
2820                 s : parseIso(match[8], sign)
2821             };
2822         } else if (duration == null) {// checks for null or undefined
2823             duration = {};
2824         } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
2825             diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
2826
2827             duration = {};
2828             duration.ms = diffRes.milliseconds;
2829             duration.M = diffRes.months;
2830         }
2831
2832         ret = new Duration(duration);
2833
2834         if (isDuration(input) && hasOwnProp(input, '_locale')) {
2835             ret._locale = input._locale;
2836         }
2837
2838         return ret;
2839     }
2840
2841     create__createDuration.fn = Duration.prototype;
2842
2843     function parseIso (inp, sign) {
2844         // We'd normally use ~~inp for this, but unfortunately it also
2845         // converts floats to ints.
2846         // inp may be undefined, so careful calling replace on it.
2847         var res = inp && parseFloat(inp.replace(',', '.'));
2848         // apply sign while we're at it
2849         return (isNaN(res) ? 0 : res) * sign;
2850     }
2851
2852     function positiveMomentsDifference(base, other) {
2853         var res = {milliseconds: 0, months: 0};
2854
2855         res.months = other.month() - base.month() +
2856             (other.year() - base.year()) * 12;
2857         if (base.clone().add(res.months, 'M').isAfter(other)) {
2858             --res.months;
2859         }
2860
2861         res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
2862
2863         return res;
2864     }
2865
2866     function momentsDifference(base, other) {
2867         var res;
2868         if (!(base.isValid() && other.isValid())) {
2869             return {milliseconds: 0, months: 0};
2870         }
2871
2872         other = cloneWithOffset(other, base);
2873         if (base.isBefore(other)) {
2874             res = positiveMomentsDifference(base, other);
2875         } else {
2876             res = positiveMomentsDifference(other, base);
2877             res.milliseconds = -res.milliseconds;
2878             res.months = -res.months;
2879         }
2880
2881         return res;
2882     }
2883
2884     // TODO: remove 'name' arg after deprecation is removed
2885     function createAdder(direction, name) {
2886         return function (val, period) {
2887             var dur, tmp;
2888             //invert the arguments, but complain about it
2889             if (period !== null && !isNaN(+period)) {
2890                 deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
2891                 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
2892                 tmp = val; val = period; period = tmp;
2893             }
2894
2895             val = typeof val === 'string' ? +val : val;
2896             dur = create__createDuration(val, period);
2897             add_subtract__addSubtract(this, dur, direction);
2898             return this;
2899         };
2900     }
2901
2902     function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
2903         var milliseconds = duration._milliseconds,
2904             days = absRound(duration._days),
2905             months = absRound(duration._months);
2906
2907         if (!mom.isValid()) {
2908             // No op
2909             return;
2910         }
2911
2912         updateOffset = updateOffset == null ? true : updateOffset;
2913
2914         if (milliseconds) {
2915             mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
2916         }
2917         if (days) {
2918             get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
2919         }
2920         if (months) {
2921             setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
2922         }
2923         if (updateOffset) {
2924             utils_hooks__hooks.updateOffset(mom, days || months);
2925         }
2926     }
2927
2928     var add_subtract__add      = createAdder(1, 'add');
2929     var add_subtract__subtract = createAdder(-1, 'subtract');
2930
2931     function getCalendarFormat(myMoment, now) {
2932         var diff = myMoment.diff(now, 'days', true);
2933         return diff < -6 ? 'sameElse' :
2934                 diff < -1 ? 'lastWeek' :
2935                 diff < 0 ? 'lastDay' :
2936                 diff < 1 ? 'sameDay' :
2937                 diff < 2 ? 'nextDay' :
2938                 diff < 7 ? 'nextWeek' : 'sameElse';
2939     }
2940
2941     function moment_calendar__calendar (time, formats) {
2942         // We want to compare the start of today, vs this.
2943         // Getting start-of-today depends on whether we're local/utc/offset or not.
2944         var now = time || local__createLocal(),
2945             sod = cloneWithOffset(now, this).startOf('day'),
2946             format = utils_hooks__hooks.calendarFormat(this, sod) || 'sameElse';
2947
2948         var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
2949
2950         return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
2951     }
2952
2953     function clone () {
2954         return new Moment(this);
2955     }
2956
2957     function isAfter (input, units) {
2958         var localInput = isMoment(input) ? input : local__createLocal(input);
2959         if (!(this.isValid() && localInput.isValid())) {
2960             return false;
2961         }
2962         units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
2963         if (units === 'millisecond') {
2964             return this.valueOf() > localInput.valueOf();
2965         } else {
2966             return localInput.valueOf() < this.clone().startOf(units).valueOf();
2967         }
2968     }
2969
2970     function isBefore (input, units) {
2971         var localInput = isMoment(input) ? input : local__createLocal(input);
2972         if (!(this.isValid() && localInput.isValid())) {
2973             return false;
2974         }
2975         units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
2976         if (units === 'millisecond') {
2977             return this.valueOf() < localInput.valueOf();
2978         } else {
2979             return this.clone().endOf(units).valueOf() < localInput.valueOf();
2980         }
2981     }
2982
2983     function isBetween (from, to, units, inclusivity) {
2984         inclusivity = inclusivity || '()';
2985         return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
2986             (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
2987     }
2988
2989     function isSame (input, units) {
2990         var localInput = isMoment(input) ? input : local__createLocal(input),
2991             inputMs;
2992         if (!(this.isValid() && localInput.isValid())) {
2993             return false;
2994         }
2995         units = normalizeUnits(units || 'millisecond');
2996         if (units === 'millisecond') {
2997             return this.valueOf() === localInput.valueOf();
2998         } else {
2999             inputMs = localInput.valueOf();
3000             return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
3001         }
3002     }
3003
3004     function isSameOrAfter (input, units) {
3005         return this.isSame(input, units) || this.isAfter(input,units);
3006     }
3007
3008     function isSameOrBefore (input, units) {
3009         return this.isSame(input, units) || this.isBefore(input,units);
3010     }
3011
3012     function diff (input, units, asFloat) {
3013         var that,
3014             zoneDelta,
3015             delta, output;
3016
3017         if (!this.isValid()) {
3018             return NaN;
3019         }
3020
3021         that = cloneWithOffset(input, this);
3022
3023         if (!that.isValid()) {
3024             return NaN;
3025         }
3026
3027         zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
3028
3029         units = normalizeUnits(units);
3030
3031         if (units === 'year' || units === 'month' || units === 'quarter') {
3032             output = monthDiff(this, that);
3033             if (units === 'quarter') {
3034                 output = output / 3;
3035             } else if (units === 'year') {
3036                 output = output / 12;
3037             }
3038         } else {
3039             delta = this - that;
3040             output = units === 'second' ? delta / 1e3 : // 1000
3041                 units === 'minute' ? delta / 6e4 : // 1000 * 60
3042                 units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
3043                 units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
3044                 units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
3045                 delta;
3046         }
3047         return asFloat ? output : absFloor(output);
3048     }
3049
3050     function monthDiff (a, b) {
3051         // difference in months
3052         var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
3053             // b is in (anchor - 1 month, anchor + 1 month)
3054             anchor = a.clone().add(wholeMonthDiff, 'months'),
3055             anchor2, adjust;
3056
3057         if (b - anchor < 0) {
3058             anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
3059             // linear across the month
3060             adjust = (b - anchor) / (anchor - anchor2);
3061         } else {
3062             anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
3063             // linear across the month
3064             adjust = (b - anchor) / (anchor2 - anchor);
3065         }
3066
3067         //check for negative zero, return zero if negative zero
3068         return -(wholeMonthDiff + adjust) || 0;
3069     }
3070
3071     utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
3072     utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
3073
3074     function toString () {
3075         return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
3076     }
3077
3078     function moment_format__toISOString () {
3079         var m = this.clone().utc();
3080         if (0 < m.year() && m.year() <= 9999) {
3081             if (isFunction(Date.prototype.toISOString)) {
3082                 // native implementation is ~50x faster, use it when we can
3083                 return this.toDate().toISOString();
3084             } else {
3085                 return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
3086             }
3087         } else {
3088             return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
3089         }
3090     }
3091
3092     function format (inputString) {
3093         if (!inputString) {
3094             inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
3095         }
3096         var output = formatMoment(this, inputString);
3097         return this.localeData().postformat(output);
3098     }
3099
3100     function from (time, withoutSuffix) {
3101         if (this.isValid() &&
3102                 ((isMoment(time) && time.isValid()) ||
3103                  local__createLocal(time).isValid())) {
3104             return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
3105         } else {
3106             return this.localeData().invalidDate();
3107         }
3108     }
3109
3110     function fromNow (withoutSuffix) {
3111         return this.from(local__createLocal(), withoutSuffix);
3112     }
3113
3114     function to (time, withoutSuffix) {
3115         if (this.isValid() &&
3116                 ((isMoment(time) && time.isValid()) ||
3117                  local__createLocal(time).isValid())) {
3118             return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
3119         } else {
3120             return this.localeData().invalidDate();
3121         }
3122     }
3123
3124     function toNow (withoutSuffix) {
3125         return this.to(local__createLocal(), withoutSuffix);
3126     }
3127
3128     // If passed a locale key, it will set the locale for this
3129     // instance.  Otherwise, it will return the locale configuration
3130     // variables for this instance.
3131     function locale (key) {
3132         var newLocaleData;
3133
3134         if (key === undefined) {
3135             return this._locale._abbr;
3136         } else {
3137             newLocaleData = locale_locales__getLocale(key);
3138             if (newLocaleData != null) {
3139                 this._locale = newLocaleData;
3140             }
3141             return this;
3142         }
3143     }
3144
3145     var lang = deprecate(
3146         'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
3147         function (key) {
3148             if (key === undefined) {
3149                 return this.localeData();
3150             } else {
3151                 return this.locale(key);
3152             }
3153         }
3154     );
3155
3156     function localeData () {
3157         return this._locale;
3158     }
3159
3160     function startOf (units) {
3161         units = normalizeUnits(units);
3162         // the following switch intentionally omits break keywords
3163         // to utilize falling through the cases.
3164         switch (units) {
3165             case 'year':
3166                 this.month(0);
3167                 /* falls through */
3168             case 'quarter':
3169             case 'month':
3170                 this.date(1);
3171                 /* falls through */
3172             case 'week':
3173             case 'isoWeek':
3174             case 'day':
3175             case 'date':
3176                 this.hours(0);
3177                 /* falls through */
3178             case 'hour':
3179                 this.minutes(0);
3180                 /* falls through */
3181             case 'minute':
3182                 this.seconds(0);
3183                 /* falls through */
3184             case 'second':
3185                 this.milliseconds(0);
3186         }
3187
3188         // weeks are a special case
3189         if (units === 'week') {
3190             this.weekday(0);
3191         }
3192         if (units === 'isoWeek') {
3193             this.isoWeekday(1);
3194         }
3195
3196         // quarters are also special
3197         if (units === 'quarter') {
3198             this.month(Math.floor(this.month() / 3) * 3);
3199         }
3200
3201         return this;
3202     }
3203
3204     function endOf (units) {
3205         units = normalizeUnits(units);
3206         if (units === undefined || units === 'millisecond') {
3207             return this;
3208         }
3209
3210         // 'date' is an alias for 'day', so it should be considered as such.
3211         if (units === 'date') {
3212             units = 'day';
3213         }
3214
3215         return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
3216     }
3217
3218     function to_type__valueOf () {
3219         return this._d.valueOf() - ((this._offset || 0) * 60000);
3220     }
3221
3222     function unix () {
3223         return Math.floor(this.valueOf() / 1000);
3224     }
3225
3226     function toDate () {
3227         return new Date(this.valueOf());
3228     }
3229
3230     function toArray () {
3231         var m = this;
3232         return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
3233     }
3234
3235     function toObject () {
3236         var m = this;
3237         return {
3238             years: m.year(),
3239             months: m.month(),
3240             date: m.date(),
3241             hours: m.hours(),
3242             minutes: m.minutes(),
3243             seconds: m.seconds(),
3244             milliseconds: m.milliseconds()
3245         };
3246     }
3247
3248     function toJSON () {
3249         // new Date(NaN).toJSON() === null
3250         return this.isValid() ? this.toISOString() : null;
3251     }
3252
3253     function moment_valid__isValid () {
3254         return valid__isValid(this);
3255     }
3256
3257     function parsingFlags () {
3258         return extend({}, getParsingFlags(this));
3259     }
3260
3261     function invalidAt () {
3262         return getParsingFlags(this).overflow;
3263     }
3264
3265     function creationData() {
3266         return {
3267             input: this._i,
3268             format: this._f,
3269             locale: this._locale,
3270             isUTC: this._isUTC,
3271             strict: this._strict
3272         };
3273     }
3274
3275     // FORMATTING
3276
3277     addFormatToken(0, ['gg', 2], 0, function () {
3278         return this.weekYear() % 100;
3279     });
3280
3281     addFormatToken(0, ['GG', 2], 0, function () {
3282         return this.isoWeekYear() % 100;
3283     });
3284
3285     function addWeekYearFormatToken (token, getter) {
3286         addFormatToken(0, [token, token.length], 0, getter);
3287     }
3288
3289     addWeekYearFormatToken('gggg',     'weekYear');
3290     addWeekYearFormatToken('ggggg',    'weekYear');
3291     addWeekYearFormatToken('GGGG',  'isoWeekYear');
3292     addWeekYearFormatToken('GGGGG', 'isoWeekYear');
3293
3294     // ALIASES
3295
3296     addUnitAlias('weekYear', 'gg');
3297     addUnitAlias('isoWeekYear', 'GG');
3298
3299     // PRIORITY
3300
3301     addUnitPriority('weekYear', 1);
3302     addUnitPriority('isoWeekYear', 1);
3303
3304
3305     // PARSING
3306
3307     addRegexToken('G',      matchSigned);
3308     addRegexToken('g',      matchSigned);
3309     addRegexToken('GG',     match1to2, match2);
3310     addRegexToken('gg',     match1to2, match2);
3311     addRegexToken('GGGG',   match1to4, match4);
3312     addRegexToken('gggg',   match1to4, match4);
3313     addRegexToken('GGGGG',  match1to6, match6);
3314     addRegexToken('ggggg',  match1to6, match6);
3315
3316     addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
3317         week[token.substr(0, 2)] = toInt(input);
3318     });
3319
3320     addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
3321         week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
3322     });
3323
3324     // MOMENTS
3325
3326     function getSetWeekYear (input) {
3327         return getSetWeekYearHelper.call(this,
3328                 input,
3329                 this.week(),
3330                 this.weekday(),
3331                 this.localeData()._week.dow,
3332                 this.localeData()._week.doy);
3333     }
3334
3335     function getSetISOWeekYear (input) {
3336         return getSetWeekYearHelper.call(this,
3337                 input, this.isoWeek(), this.isoWeekday(), 1, 4);
3338     }
3339
3340     function getISOWeeksInYear () {
3341         return weeksInYear(this.year(), 1, 4);
3342     }
3343
3344     function getWeeksInYear () {
3345         var weekInfo = this.localeData()._week;
3346         return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
3347     }
3348
3349     function getSetWeekYearHelper(input, week, weekday, dow, doy) {
3350         var weeksTarget;
3351         if (input == null) {
3352             return weekOfYear(this, dow, doy).year;
3353         } else {
3354             weeksTarget = weeksInYear(input, dow, doy);
3355             if (week > weeksTarget) {
3356                 week = weeksTarget;
3357             }
3358             return setWeekAll.call(this, input, week, weekday, dow, doy);
3359         }
3360     }
3361
3362     function setWeekAll(weekYear, week, weekday, dow, doy) {
3363         var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
3364             date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
3365
3366         this.year(date.getUTCFullYear());
3367         this.month(date.getUTCMonth());
3368         this.date(date.getUTCDate());
3369         return this;
3370     }
3371
3372     // FORMATTING
3373
3374     addFormatToken('Q', 0, 'Qo', 'quarter');
3375
3376     // ALIASES
3377
3378     addUnitAlias('quarter', 'Q');
3379
3380     // PRIORITY
3381
3382     addUnitPriority('quarter', 7);
3383
3384     // PARSING
3385
3386     addRegexToken('Q', match1);
3387     addParseToken('Q', function (input, array) {
3388         array[MONTH] = (toInt(input) - 1) * 3;
3389     });
3390
3391     // MOMENTS
3392
3393     function getSetQuarter (input) {
3394         return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
3395     }
3396
3397     // FORMATTING
3398
3399     addFormatToken('D', ['DD', 2], 'Do', 'date');
3400
3401     // ALIASES
3402
3403     addUnitAlias('date', 'D');
3404
3405     // PRIOROITY
3406     addUnitPriority('date', 9);
3407
3408     // PARSING
3409
3410     addRegexToken('D',  match1to2);
3411     addRegexToken('DD', match1to2, match2);
3412     addRegexToken('Do', function (isStrict, locale) {
3413         return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
3414     });
3415
3416     addParseToken(['D', 'DD'], DATE);
3417     addParseToken('Do', function (input, array) {
3418         array[DATE] = toInt(input.match(match1to2)[0], 10);
3419     });
3420
3421     // MOMENTS
3422
3423     var getSetDayOfMonth = makeGetSet('Date', true);
3424
3425     // FORMATTING
3426
3427     addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
3428
3429     // ALIASES
3430
3431     addUnitAlias('dayOfYear', 'DDD');
3432
3433     // PRIORITY
3434     addUnitPriority('dayOfYear', 4);
3435
3436     // PARSING
3437
3438     addRegexToken('DDD',  match1to3);
3439     addRegexToken('DDDD', match3);
3440     addParseToken(['DDD', 'DDDD'], function (input, array, config) {
3441         config._dayOfYear = toInt(input);
3442     });
3443
3444     // HELPERS
3445
3446     // MOMENTS
3447
3448     function getSetDayOfYear (input) {
3449         var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
3450         return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
3451     }
3452
3453     // FORMATTING
3454
3455     addFormatToken('m', ['mm', 2], 0, 'minute');
3456
3457     // ALIASES
3458
3459     addUnitAlias('minute', 'm');
3460
3461     // PRIORITY
3462
3463     addUnitPriority('minute', 14);
3464
3465     // PARSING
3466
3467     addRegexToken('m',  match1to2);
3468     addRegexToken('mm', match1to2, match2);
3469     addParseToken(['m', 'mm'], MINUTE);
3470
3471     // MOMENTS
3472
3473     var getSetMinute = makeGetSet('Minutes', false);
3474
3475     // FORMATTING
3476
3477     addFormatToken('s', ['ss', 2], 0, 'second');
3478
3479     // ALIASES
3480
3481     addUnitAlias('second', 's');
3482
3483     // PRIORITY
3484
3485     addUnitPriority('second', 15);
3486
3487     // PARSING
3488
3489     addRegexToken('s',  match1to2);
3490     addRegexToken('ss', match1to2, match2);
3491     addParseToken(['s', 'ss'], SECOND);
3492
3493     // MOMENTS
3494
3495     var getSetSecond = makeGetSet('Seconds', false);
3496
3497     // FORMATTING
3498
3499     addFormatToken('S', 0, 0, function () {
3500         return ~~(this.millisecond() / 100);
3501     });
3502
3503     addFormatToken(0, ['SS', 2], 0, function () {
3504         return ~~(this.millisecond() / 10);
3505     });
3506
3507     addFormatToken(0, ['SSS', 3], 0, 'millisecond');
3508     addFormatToken(0, ['SSSS', 4], 0, function () {
3509         return this.millisecond() * 10;
3510     });
3511     addFormatToken(0, ['SSSSS', 5], 0, function () {
3512         return this.millisecond() * 100;
3513     });
3514     addFormatToken(0, ['SSSSSS', 6], 0, function () {
3515         return this.millisecond() * 1000;
3516     });
3517     addFormatToken(0, ['SSSSSSS', 7], 0, function () {
3518         return this.millisecond() * 10000;
3519     });
3520     addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
3521         return this.millisecond() * 100000;
3522     });
3523     addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
3524         return this.millisecond() * 1000000;
3525     });
3526
3527
3528     // ALIASES
3529
3530     addUnitAlias('millisecond', 'ms');
3531
3532     // PRIORITY
3533
3534     addUnitPriority('millisecond', 16);
3535
3536     // PARSING
3537
3538     addRegexToken('S',    match1to3, match1);
3539     addRegexToken('SS',   match1to3, match2);
3540     addRegexToken('SSS',  match1to3, match3);
3541
3542     var token;
3543     for (token = 'SSSS'; token.length <= 9; token += 'S') {
3544         addRegexToken(token, matchUnsigned);
3545     }
3546
3547     function parseMs(input, array) {
3548         array[MILLISECOND] = toInt(('0.' + input) * 1000);
3549     }
3550
3551     for (token = 'S'; token.length <= 9; token += 'S') {
3552         addParseToken(token, parseMs);
3553     }
3554     // MOMENTS
3555
3556     var getSetMillisecond = makeGetSet('Milliseconds', false);
3557
3558     // FORMATTING
3559
3560     addFormatToken('z',  0, 0, 'zoneAbbr');
3561     addFormatToken('zz', 0, 0, 'zoneName');
3562
3563     // MOMENTS
3564
3565     function getZoneAbbr () {
3566         return this._isUTC ? 'UTC' : '';
3567     }
3568
3569     function getZoneName () {
3570         return this._isUTC ? 'Coordinated Universal Time' : '';
3571     }
3572
3573     var momentPrototype__proto = Moment.prototype;
3574
3575     momentPrototype__proto.add               = add_subtract__add;
3576     momentPrototype__proto.calendar          = moment_calendar__calendar;
3577     momentPrototype__proto.clone             = clone;
3578     momentPrototype__proto.diff              = diff;
3579     momentPrototype__proto.endOf             = endOf;
3580     momentPrototype__proto.format            = format;
3581     momentPrototype__proto.from              = from;
3582     momentPrototype__proto.fromNow           = fromNow;
3583     momentPrototype__proto.to                = to;
3584     momentPrototype__proto.toNow             = toNow;
3585     momentPrototype__proto.get               = stringGet;
3586     momentPrototype__proto.invalidAt         = invalidAt;
3587     momentPrototype__proto.isAfter           = isAfter;
3588     momentPrototype__proto.isBefore          = isBefore;
3589     momentPrototype__proto.isBetween         = isBetween;
3590     momentPrototype__proto.isSame            = isSame;
3591     momentPrototype__proto.isSameOrAfter     = isSameOrAfter;
3592     momentPrototype__proto.isSameOrBefore    = isSameOrBefore;
3593     momentPrototype__proto.isValid           = moment_valid__isValid;
3594     momentPrototype__proto.lang              = lang;
3595     momentPrototype__proto.locale            = locale;
3596     momentPrototype__proto.localeData        = localeData;
3597     momentPrototype__proto.max               = prototypeMax;
3598     momentPrototype__proto.min               = prototypeMin;
3599     momentPrototype__proto.parsingFlags      = parsingFlags;
3600     momentPrototype__proto.set               = stringSet;
3601     momentPrototype__proto.startOf           = startOf;
3602     momentPrototype__proto.subtract          = add_subtract__subtract;
3603     momentPrototype__proto.toArray           = toArray;
3604     momentPrototype__proto.toObject          = toObject;
3605     momentPrototype__proto.toDate            = toDate;
3606     momentPrototype__proto.toISOString       = moment_format__toISOString;
3607     momentPrototype__proto.toJSON            = toJSON;
3608     momentPrototype__proto.toString          = toString;
3609     momentPrototype__proto.unix              = unix;
3610     momentPrototype__proto.valueOf           = to_type__valueOf;
3611     momentPrototype__proto.creationData      = creationData;
3612
3613     // Year
3614     momentPrototype__proto.year       = getSetYear;
3615     momentPrototype__proto.isLeapYear = getIsLeapYear;
3616
3617     // Week Year
3618     momentPrototype__proto.weekYear    = getSetWeekYear;
3619     momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
3620
3621     // Quarter
3622     momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
3623
3624     // Month
3625     momentPrototype__proto.month       = getSetMonth;
3626     momentPrototype__proto.daysInMonth = getDaysInMonth;
3627
3628     // Week
3629     momentPrototype__proto.week           = momentPrototype__proto.weeks        = getSetWeek;
3630     momentPrototype__proto.isoWeek        = momentPrototype__proto.isoWeeks     = getSetISOWeek;
3631     momentPrototype__proto.weeksInYear    = getWeeksInYear;
3632     momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
3633
3634     // Day
3635     momentPrototype__proto.date       = getSetDayOfMonth;
3636     momentPrototype__proto.day        = momentPrototype__proto.days             = getSetDayOfWeek;
3637     momentPrototype__proto.weekday    = getSetLocaleDayOfWeek;
3638     momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
3639     momentPrototype__proto.dayOfYear  = getSetDayOfYear;
3640
3641     // Hour
3642     momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
3643
3644     // Minute
3645     momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
3646
3647     // Second
3648     momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
3649
3650     // Millisecond
3651     momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
3652
3653     // Offset
3654     momentPrototype__proto.utcOffset            = getSetOffset;
3655     momentPrototype__proto.utc                  = setOffsetToUTC;
3656     momentPrototype__proto.local                = setOffsetToLocal;
3657     momentPrototype__proto.parseZone            = setOffsetToParsedOffset;
3658     momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
3659     momentPrototype__proto.isDST                = isDaylightSavingTime;
3660     momentPrototype__proto.isLocal              = isLocal;
3661     momentPrototype__proto.isUtcOffset          = isUtcOffset;
3662     momentPrototype__proto.isUtc                = isUtc;
3663     momentPrototype__proto.isUTC                = isUtc;
3664
3665     // Timezone
3666     momentPrototype__proto.zoneAbbr = getZoneAbbr;
3667     momentPrototype__proto.zoneName = getZoneName;
3668
3669     // Deprecations
3670     momentPrototype__proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
3671     momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
3672     momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
3673     momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
3674     momentPrototype__proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
3675
3676     var momentPrototype = momentPrototype__proto;
3677
3678     function moment__createUnix (input) {
3679         return local__createLocal(input * 1000);
3680     }
3681
3682     function moment__createInZone () {
3683         return local__createLocal.apply(null, arguments).parseZone();
3684     }
3685
3686     function preParsePostFormat (string) {
3687         return string;
3688     }
3689
3690     var prototype__proto = Locale.prototype;
3691
3692     prototype__proto.calendar        = locale_calendar__calendar;
3693     prototype__proto.longDateFormat  = longDateFormat;
3694     prototype__proto.invalidDate     = invalidDate;
3695     prototype__proto.ordinal         = ordinal;
3696     prototype__proto.preparse        = preParsePostFormat;
3697     prototype__proto.postformat      = preParsePostFormat;
3698     prototype__proto.relativeTime    = relative__relativeTime;
3699     prototype__proto.pastFuture      = pastFuture;
3700     prototype__proto.set             = locale_set__set;
3701
3702     // Month
3703     prototype__proto.months            =        localeMonths;
3704     prototype__proto.monthsShort       =        localeMonthsShort;
3705     prototype__proto.monthsParse       =        localeMonthsParse;
3706     prototype__proto.monthsRegex       = monthsRegex;
3707     prototype__proto.monthsShortRegex  = monthsShortRegex;
3708
3709     // Week
3710     prototype__proto.week = localeWeek;
3711     prototype__proto.firstDayOfYear = localeFirstDayOfYear;
3712     prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
3713
3714     // Day of Week
3715     prototype__proto.weekdays       =        localeWeekdays;
3716     prototype__proto.weekdaysMin    =        localeWeekdaysMin;
3717     prototype__proto.weekdaysShort  =        localeWeekdaysShort;
3718     prototype__proto.weekdaysParse  =        localeWeekdaysParse;
3719
3720     prototype__proto.weekdaysRegex       =        weekdaysRegex;
3721     prototype__proto.weekdaysShortRegex  =        weekdaysShortRegex;
3722     prototype__proto.weekdaysMinRegex    =        weekdaysMinRegex;
3723
3724     // Hours
3725     prototype__proto.isPM = localeIsPM;
3726     prototype__proto.meridiem = localeMeridiem;
3727
3728     function lists__get (format, index, field, setter) {
3729         var locale = locale_locales__getLocale();
3730         var utc = create_utc__createUTC().set(setter, index);
3731         return locale[field](utc, format);
3732     }
3733
3734     function listMonthsImpl (format, index, field) {
3735         if (typeof format === 'number') {
3736             index = format;
3737             format = undefined;
3738         }
3739
3740         format = format || '';
3741
3742         if (index != null) {
3743             return lists__get(format, index, field, 'month');
3744         }
3745
3746         var i;
3747         var out = [];
3748         for (i = 0; i < 12; i++) {
3749             out[i] = lists__get(format, i, field, 'month');
3750         }
3751         return out;
3752     }
3753
3754     // ()
3755     // (5)
3756     // (fmt, 5)
3757     // (fmt)
3758     // (true)
3759     // (true, 5)
3760     // (true, fmt, 5)
3761     // (true, fmt)
3762     function listWeekdaysImpl (localeSorted, format, index, field) {
3763         if (typeof localeSorted === 'boolean') {
3764             if (typeof format === 'number') {
3765                 index = format;
3766                 format = undefined;
3767             }
3768
3769             format = format || '';
3770         } else {
3771             format = localeSorted;
3772             index = format;
3773             localeSorted = false;
3774
3775             if (typeof format === 'number') {
3776                 index = format;
3777                 format = undefined;
3778             }
3779
3780             format = format || '';
3781         }
3782
3783         var locale = locale_locales__getLocale(),
3784             shift = localeSorted ? locale._week.dow : 0;
3785
3786         if (index != null) {
3787             return lists__get(format, (index + shift) % 7, field, 'day');
3788         }
3789
3790         var i;
3791         var out = [];
3792         for (i = 0; i < 7; i++) {
3793             out[i] = lists__get(format, (i + shift) % 7, field, 'day');
3794         }
3795         return out;
3796     }
3797
3798     function lists__listMonths (format, index) {
3799         return listMonthsImpl(format, index, 'months');
3800     }
3801
3802     function lists__listMonthsShort (format, index) {
3803         return listMonthsImpl(format, index, 'monthsShort');
3804     }
3805
3806     function lists__listWeekdays (localeSorted, format, index) {
3807         return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
3808     }
3809
3810     function lists__listWeekdaysShort (localeSorted, format, index) {
3811         return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
3812     }
3813
3814     function lists__listWeekdaysMin (localeSorted, format, index) {
3815         return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
3816     }
3817
3818     locale_locales__getSetGlobalLocale('en', {
3819         ordinalParse: /\d{1,2}(th|st|nd|rd)/,
3820         ordinal : function (number) {
3821             var b = number % 10,
3822                 output = (toInt(number % 100 / 10) === 1) ? 'th' :
3823                 (b === 1) ? 'st' :
3824                 (b === 2) ? 'nd' :
3825                 (b === 3) ? 'rd' : 'th';
3826             return number + output;
3827         }
3828     });
3829
3830     // Side effect imports
3831     utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
3832     utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
3833
3834     var mathAbs = Math.abs;
3835
3836     function duration_abs__abs () {
3837         var data           = this._data;
3838
3839         this._milliseconds = mathAbs(this._milliseconds);
3840         this._days         = mathAbs(this._days);
3841         this._months       = mathAbs(this._months);
3842
3843         data.milliseconds  = mathAbs(data.milliseconds);
3844         data.seconds       = mathAbs(data.seconds);
3845         data.minutes       = mathAbs(data.minutes);
3846         data.hours         = mathAbs(data.hours);
3847         data.months        = mathAbs(data.months);
3848         data.years         = mathAbs(data.years);
3849
3850         return this;
3851     }
3852
3853     function duration_add_subtract__addSubtract (duration, input, value, direction) {
3854         var other = create__createDuration(input, value);
3855
3856         duration._milliseconds += direction * other._milliseconds;
3857         duration._days         += direction * other._days;
3858         duration._months       += direction * other._months;
3859
3860         return duration._bubble();
3861     }
3862
3863     // supports only 2.0-style add(1, 's') or add(duration)
3864     function duration_add_subtract__add (input, value) {
3865         return duration_add_subtract__addSubtract(this, input, value, 1);
3866     }
3867
3868     // supports only 2.0-style subtract(1, 's') or subtract(duration)
3869     function duration_add_subtract__subtract (input, value) {
3870         return duration_add_subtract__addSubtract(this, input, value, -1);
3871     }
3872
3873     function absCeil (number) {
3874         if (number < 0) {
3875             return Math.floor(number);
3876         } else {
3877             return Math.ceil(number);
3878         }
3879     }
3880
3881     function bubble () {
3882         var milliseconds = this._milliseconds;
3883         var days         = this._days;
3884         var months       = this._months;
3885         var data         = this._data;
3886         var seconds, minutes, hours, years, monthsFromDays;
3887
3888         // if we have a mix of positive and negative values, bubble down first
3889         // check: https://github.com/moment/moment/issues/2166
3890         if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
3891                 (milliseconds <= 0 && days <= 0 && months <= 0))) {
3892             milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
3893             days = 0;
3894             months = 0;
3895         }
3896
3897         // The following code bubbles up values, see the tests for
3898         // examples of what that means.
3899         data.milliseconds = milliseconds % 1000;
3900
3901         seconds           = absFloor(milliseconds / 1000);
3902         data.seconds      = seconds % 60;
3903
3904         minutes           = absFloor(seconds / 60);
3905         data.minutes      = minutes % 60;
3906
3907         hours             = absFloor(minutes / 60);
3908         data.hours        = hours % 24;
3909
3910         days += absFloor(hours / 24);
3911
3912         // convert days to months
3913         monthsFromDays = absFloor(daysToMonths(days));
3914         months += monthsFromDays;
3915         days -= absCeil(monthsToDays(monthsFromDays));
3916
3917         // 12 months -> 1 year
3918         years = absFloor(months / 12);
3919         months %= 12;
3920
3921         data.days   = days;
3922         data.months = months;
3923         data.years  = years;
3924
3925         return this;
3926     }
3927
3928     function daysToMonths (days) {
3929         // 400 years have 146097 days (taking into account leap year rules)
3930         // 400 years have 12 months === 4800
3931         return days * 4800 / 146097;
3932     }
3933
3934     function monthsToDays (months) {
3935         // the reverse of daysToMonths
3936         return months * 146097 / 4800;
3937     }
3938
3939     function as (units) {
3940         var days;
3941         var months;
3942         var milliseconds = this._milliseconds;
3943
3944         units = normalizeUnits(units);
3945
3946         if (units === 'month' || units === 'year') {
3947             days   = this._days   + milliseconds / 864e5;
3948             months = this._months + daysToMonths(days);
3949             return units === 'month' ? months : months / 12;
3950         } else {
3951             // handle milliseconds separately because of floating point math errors (issue #1867)
3952             days = this._days + Math.round(monthsToDays(this._months));
3953             switch (units) {
3954                 case 'week'   : return days / 7     + milliseconds / 6048e5;
3955                 case 'day'    : return days         + milliseconds / 864e5;
3956                 case 'hour'   : return days * 24    + milliseconds / 36e5;
3957                 case 'minute' : return days * 1440  + milliseconds / 6e4;
3958                 case 'second' : return days * 86400 + milliseconds / 1000;
3959                 // Math.floor prevents floating point math errors here
3960                 case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
3961                 default: throw new Error('Unknown unit ' + units);
3962             }
3963         }
3964     }
3965
3966     // TODO: Use this.as('ms')?
3967     function duration_as__valueOf () {
3968         return (
3969             this._milliseconds +
3970             this._days * 864e5 +
3971             (this._months % 12) * 2592e6 +
3972             toInt(this._months / 12) * 31536e6
3973         );
3974     }
3975
3976     function makeAs (alias) {
3977         return function () {
3978             return this.as(alias);
3979         };
3980     }
3981
3982     var asMilliseconds = makeAs('ms');
3983     var asSeconds      = makeAs('s');
3984     var asMinutes      = makeAs('m');
3985     var asHours        = makeAs('h');
3986     var asDays         = makeAs('d');
3987     var asWeeks        = makeAs('w');
3988     var asMonths       = makeAs('M');
3989     var asYears        = makeAs('y');
3990
3991     function duration_get__get (units) {
3992         units = normalizeUnits(units);
3993         return this[units + 's']();
3994     }
3995
3996     function makeGetter(name) {
3997         return function () {
3998             return this._data[name];
3999         };
4000     }
4001
4002     var milliseconds = makeGetter('milliseconds');
4003     var seconds      = makeGetter('seconds');
4004     var minutes      = makeGetter('minutes');
4005     var hours        = makeGetter('hours');
4006     var days         = makeGetter('days');
4007     var months       = makeGetter('months');
4008     var years        = makeGetter('years');
4009
4010     function weeks () {
4011         return absFloor(this.days() / 7);
4012     }
4013
4014     var round = Math.round;
4015     var thresholds = {
4016         s: 45,  // seconds to minute
4017         m: 45,  // minutes to hour
4018         h: 22,  // hours to day
4019         d: 26,  // days to month
4020         M: 11   // months to year
4021     };
4022
4023     // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
4024     function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
4025         return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
4026     }
4027
4028     function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
4029         var duration = create__createDuration(posNegDuration).abs();
4030         var seconds  = round(duration.as('s'));
4031         var minutes  = round(duration.as('m'));
4032         var hours    = round(duration.as('h'));
4033         var days     = round(duration.as('d'));
4034         var months   = round(duration.as('M'));
4035         var years    = round(duration.as('y'));
4036
4037         var a = seconds < thresholds.s && ['s', seconds]  ||
4038                 minutes <= 1           && ['m']           ||
4039                 minutes < thresholds.m && ['mm', minutes] ||
4040                 hours   <= 1           && ['h']           ||
4041                 hours   < thresholds.h && ['hh', hours]   ||
4042                 days    <= 1           && ['d']           ||
4043                 days    < thresholds.d && ['dd', days]    ||
4044                 months  <= 1           && ['M']           ||
4045                 months  < thresholds.M && ['MM', months]  ||
4046                 years   <= 1           && ['y']           || ['yy', years];
4047
4048         a[2] = withoutSuffix;
4049         a[3] = +posNegDuration > 0;
4050         a[4] = locale;
4051         return substituteTimeAgo.apply(null, a);
4052     }
4053
4054     // This function allows you to set the rounding function for relative time strings
4055     function duration_humanize__getSetRelativeTimeRounding (roundingFunction) {
4056         if (roundingFunction === undefined) {
4057             return round;
4058         }
4059         if (typeof(roundingFunction) === 'function') {
4060             round = roundingFunction;
4061             return true;
4062         }
4063         return false;
4064     }
4065
4066     // This function allows you to set a threshold for relative time strings
4067     function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
4068         if (thresholds[threshold] === undefined) {
4069             return false;
4070         }
4071         if (limit === undefined) {
4072             return thresholds[threshold];
4073         }
4074         thresholds[threshold] = limit;
4075         return true;
4076     }
4077
4078     function humanize (withSuffix) {
4079         var locale = this.localeData();
4080         var output = duration_humanize__relativeTime(this, !withSuffix, locale);
4081
4082         if (withSuffix) {
4083             output = locale.pastFuture(+this, output);
4084         }
4085
4086         return locale.postformat(output);
4087     }
4088
4089     var iso_string__abs = Math.abs;
4090
4091     function iso_string__toISOString() {
4092         // for ISO strings we do not use the normal bubbling rules:
4093         //  * milliseconds bubble up until they become hours
4094         //  * days do not bubble at all
4095         //  * months bubble up until they become years
4096         // This is because there is no context-free conversion between hours and days
4097         // (think of clock changes)
4098         // and also not between days and months (28-31 days per month)
4099         var seconds = iso_string__abs(this._milliseconds) / 1000;
4100         var days         = iso_string__abs(this._days);
4101         var months       = iso_string__abs(this._months);
4102         var minutes, hours, years;
4103
4104         // 3600 seconds -> 60 minutes -> 1 hour
4105         minutes           = absFloor(seconds / 60);
4106         hours             = absFloor(minutes / 60);
4107         seconds %= 60;
4108         minutes %= 60;
4109
4110         // 12 months -> 1 year
4111         years  = absFloor(months / 12);
4112         months %= 12;
4113
4114
4115         // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
4116         var Y = years;
4117         var M = months;
4118         var D = days;
4119         var h = hours;
4120         var m = minutes;
4121         var s = seconds;
4122         var total = this.asSeconds();
4123
4124         if (!total) {
4125             // this is the same as C#'s (Noda) and python (isodate)...
4126             // but not other JS (goog.date)
4127             return 'P0D';
4128         }
4129
4130         return (total < 0 ? '-' : '') +
4131             'P' +
4132             (Y ? Y + 'Y' : '') +
4133             (M ? M + 'M' : '') +
4134             (D ? D + 'D' : '') +
4135             ((h || m || s) ? 'T' : '') +
4136             (h ? h + 'H' : '') +
4137             (m ? m + 'M' : '') +
4138             (s ? s + 'S' : '');
4139     }
4140
4141     var duration_prototype__proto = Duration.prototype;
4142
4143     duration_prototype__proto.abs            = duration_abs__abs;
4144     duration_prototype__proto.add            = duration_add_subtract__add;
4145     duration_prototype__proto.subtract       = duration_add_subtract__subtract;
4146     duration_prototype__proto.as             = as;
4147     duration_prototype__proto.asMilliseconds = asMilliseconds;
4148     duration_prototype__proto.asSeconds      = asSeconds;
4149     duration_prototype__proto.asMinutes      = asMinutes;
4150     duration_prototype__proto.asHours        = asHours;
4151     duration_prototype__proto.asDays         = asDays;
4152     duration_prototype__proto.asWeeks        = asWeeks;
4153     duration_prototype__proto.asMonths       = asMonths;
4154     duration_prototype__proto.asYears        = asYears;
4155     duration_prototype__proto.valueOf        = duration_as__valueOf;
4156     duration_prototype__proto._bubble        = bubble;
4157     duration_prototype__proto.get            = duration_get__get;
4158     duration_prototype__proto.milliseconds   = milliseconds;
4159     duration_prototype__proto.seconds        = seconds;
4160     duration_prototype__proto.minutes        = minutes;
4161     duration_prototype__proto.hours          = hours;
4162     duration_prototype__proto.days           = days;
4163     duration_prototype__proto.weeks          = weeks;
4164     duration_prototype__proto.months         = months;
4165     duration_prototype__proto.years          = years;
4166     duration_prototype__proto.humanize       = humanize;
4167     duration_prototype__proto.toISOString    = iso_string__toISOString;
4168     duration_prototype__proto.toString       = iso_string__toISOString;
4169     duration_prototype__proto.toJSON         = iso_string__toISOString;
4170     duration_prototype__proto.locale         = locale;
4171     duration_prototype__proto.localeData     = localeData;
4172
4173     // Deprecations
4174     duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
4175     duration_prototype__proto.lang = lang;
4176
4177     // Side effect imports
4178
4179     // FORMATTING
4180
4181     addFormatToken('X', 0, 0, 'unix');
4182     addFormatToken('x', 0, 0, 'valueOf');
4183
4184     // PARSING
4185
4186     addRegexToken('x', matchSigned);
4187     addRegexToken('X', matchTimestamp);
4188     addParseToken('X', function (input, array, config) {
4189         config._d = new Date(parseFloat(input, 10) * 1000);
4190     });
4191     addParseToken('x', function (input, array, config) {
4192         config._d = new Date(toInt(input));
4193     });
4194
4195     // Side effect imports
4196
4197
4198     utils_hooks__hooks.version = '2.15.1';
4199
4200     setHookCallback(local__createLocal);
4201
4202     utils_hooks__hooks.fn                    = momentPrototype;
4203     utils_hooks__hooks.min                   = min;
4204     utils_hooks__hooks.max                   = max;
4205     utils_hooks__hooks.now                   = now;
4206     utils_hooks__hooks.utc                   = create_utc__createUTC;
4207     utils_hooks__hooks.unix                  = moment__createUnix;
4208     utils_hooks__hooks.months                = lists__listMonths;
4209     utils_hooks__hooks.isDate                = isDate;
4210     utils_hooks__hooks.locale                = locale_locales__getSetGlobalLocale;
4211     utils_hooks__hooks.invalid               = valid__createInvalid;
4212     utils_hooks__hooks.duration              = create__createDuration;
4213     utils_hooks__hooks.isMoment              = isMoment;
4214     utils_hooks__hooks.weekdays              = lists__listWeekdays;
4215     utils_hooks__hooks.parseZone             = moment__createInZone;
4216     utils_hooks__hooks.localeData            = locale_locales__getLocale;
4217     utils_hooks__hooks.isDuration            = isDuration;
4218     utils_hooks__hooks.monthsShort           = lists__listMonthsShort;
4219     utils_hooks__hooks.weekdaysMin           = lists__listWeekdaysMin;
4220     utils_hooks__hooks.defineLocale          = defineLocale;
4221     utils_hooks__hooks.updateLocale          = updateLocale;
4222     utils_hooks__hooks.locales               = locale_locales__listLocales;
4223     utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
4224     utils_hooks__hooks.normalizeUnits        = normalizeUnits;
4225     utils_hooks__hooks.relativeTimeRounding = duration_humanize__getSetRelativeTimeRounding;
4226     utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
4227     utils_hooks__hooks.calendarFormat        = getCalendarFormat;
4228     utils_hooks__hooks.prototype             = momentPrototype;
4229
4230     var _moment = utils_hooks__hooks;
4231
4232     return _moment;
4233
4234 }));