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