update and move moment.js to separate directory
[qcg-portal.git] / qcg / static / qcg / moment / moment.js
1 //! moment.js
2 //! version : 2.9.0
3 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4 //! license : MIT
5 //! momentjs.com
6
7 (function (undefined) {
8     /************************************
9         Constants
10     ************************************/
11
12     var moment,
13         VERSION = '2.9.0',
14         // the global-scope this is NOT the global object in Node.js
15         globalScope = (typeof global !== 'undefined' && (typeof window === 'undefined' || window === global.window)) ? global : this,
16         oldGlobalMoment,
17         round = Math.round,
18         hasOwnProperty = Object.prototype.hasOwnProperty,
19         i,
20
21         YEAR = 0,
22         MONTH = 1,
23         DATE = 2,
24         HOUR = 3,
25         MINUTE = 4,
26         SECOND = 5,
27         MILLISECOND = 6,
28
29         // internal storage for locale config files
30         locales = {},
31
32         // extra moment internal properties (plugins register props here)
33         momentProperties = [],
34
35         // check for nodeJS
36         hasModule = (typeof module !== 'undefined' && module && module.exports),
37
38         // ASP.NET json date format regex
39         aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
40         aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
41
42         // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
43         // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
44         isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
45
46         // format tokens
47         formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,
48         localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
49
50         // parsing token regexes
51         parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
52         parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
53         parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
54         parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
55         parseTokenDigits = /\d+/, // nonzero number of digits
56         parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
57         parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
58         parseTokenT = /T/i, // T (ISO separator)
59         parseTokenOffsetMs = /[\+\-]?\d+/, // 1234567890123
60         parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
61
62         //strict parsing regexes
63         parseTokenOneDigit = /\d/, // 0 - 9
64         parseTokenTwoDigits = /\d\d/, // 00 - 99
65         parseTokenThreeDigits = /\d{3}/, // 000 - 999
66         parseTokenFourDigits = /\d{4}/, // 0000 - 9999
67         parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
68         parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
69
70         // iso 8601 regex
71         // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
72         isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,
73
74         isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
75
76         isoDates = [
77             ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
78             ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
79             ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
80             ['GGGG-[W]WW', /\d{4}-W\d{2}/],
81             ['YYYY-DDD', /\d{4}-\d{3}/]
82         ],
83
84         // iso time formats and regexes
85         isoTimes = [
86             ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/],
87             ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
88             ['HH:mm', /(T| )\d\d:\d\d/],
89             ['HH', /(T| )\d\d/]
90         ],
91
92         // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-', '15', '30']
93         parseTimezoneChunker = /([\+\-]|\d\d)/gi,
94
95         // getter and setter names
96         proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
97         unitMillisecondFactors = {
98             'Milliseconds' : 1,
99             'Seconds' : 1e3,
100             'Minutes' : 6e4,
101             'Hours' : 36e5,
102             'Days' : 864e5,
103             'Months' : 2592e6,
104             'Years' : 31536e6
105         },
106
107         unitAliases = {
108             ms : 'millisecond',
109             s : 'second',
110             m : 'minute',
111             h : 'hour',
112             d : 'day',
113             D : 'date',
114             w : 'week',
115             W : 'isoWeek',
116             M : 'month',
117             Q : 'quarter',
118             y : 'year',
119             DDD : 'dayOfYear',
120             e : 'weekday',
121             E : 'isoWeekday',
122             gg: 'weekYear',
123             GG: 'isoWeekYear'
124         },
125
126         camelFunctions = {
127             dayofyear : 'dayOfYear',
128             isoweekday : 'isoWeekday',
129             isoweek : 'isoWeek',
130             weekyear : 'weekYear',
131             isoweekyear : 'isoWeekYear'
132         },
133
134         // format function strings
135         formatFunctions = {},
136
137         // default relative time thresholds
138         relativeTimeThresholds = {
139             s: 45,  // seconds to minute
140             m: 45,  // minutes to hour
141             h: 22,  // hours to day
142             d: 26,  // days to month
143             M: 11   // months to year
144         },
145
146         // tokens to ordinalize and pad
147         ordinalizeTokens = 'DDD w W M D d'.split(' '),
148         paddedTokens = 'M D H h m s w W'.split(' '),
149
150         formatTokenFunctions = {
151             M    : function () {
152                 return this.month() + 1;
153             },
154             MMM  : function (format) {
155                 return this.localeData().monthsShort(this, format);
156             },
157             MMMM : function (format) {
158                 return this.localeData().months(this, format);
159             },
160             D    : function () {
161                 return this.date();
162             },
163             DDD  : function () {
164                 return this.dayOfYear();
165             },
166             d    : function () {
167                 return this.day();
168             },
169             dd   : function (format) {
170                 return this.localeData().weekdaysMin(this, format);
171             },
172             ddd  : function (format) {
173                 return this.localeData().weekdaysShort(this, format);
174             },
175             dddd : function (format) {
176                 return this.localeData().weekdays(this, format);
177             },
178             w    : function () {
179                 return this.week();
180             },
181             W    : function () {
182                 return this.isoWeek();
183             },
184             YY   : function () {
185                 return leftZeroFill(this.year() % 100, 2);
186             },
187             YYYY : function () {
188                 return leftZeroFill(this.year(), 4);
189             },
190             YYYYY : function () {
191                 return leftZeroFill(this.year(), 5);
192             },
193             YYYYYY : function () {
194                 var y = this.year(), sign = y >= 0 ? '+' : '-';
195                 return sign + leftZeroFill(Math.abs(y), 6);
196             },
197             gg   : function () {
198                 return leftZeroFill(this.weekYear() % 100, 2);
199             },
200             gggg : function () {
201                 return leftZeroFill(this.weekYear(), 4);
202             },
203             ggggg : function () {
204                 return leftZeroFill(this.weekYear(), 5);
205             },
206             GG   : function () {
207                 return leftZeroFill(this.isoWeekYear() % 100, 2);
208             },
209             GGGG : function () {
210                 return leftZeroFill(this.isoWeekYear(), 4);
211             },
212             GGGGG : function () {
213                 return leftZeroFill(this.isoWeekYear(), 5);
214             },
215             e : function () {
216                 return this.weekday();
217             },
218             E : function () {
219                 return this.isoWeekday();
220             },
221             a    : function () {
222                 return this.localeData().meridiem(this.hours(), this.minutes(), true);
223             },
224             A    : function () {
225                 return this.localeData().meridiem(this.hours(), this.minutes(), false);
226             },
227             H    : function () {
228                 return this.hours();
229             },
230             h    : function () {
231                 return this.hours() % 12 || 12;
232             },
233             m    : function () {
234                 return this.minutes();
235             },
236             s    : function () {
237                 return this.seconds();
238             },
239             S    : function () {
240                 return toInt(this.milliseconds() / 100);
241             },
242             SS   : function () {
243                 return leftZeroFill(toInt(this.milliseconds() / 10), 2);
244             },
245             SSS  : function () {
246                 return leftZeroFill(this.milliseconds(), 3);
247             },
248             SSSS : function () {
249                 return leftZeroFill(this.milliseconds(), 3);
250             },
251             Z    : function () {
252                 var a = this.utcOffset(),
253                     b = '+';
254                 if (a < 0) {
255                     a = -a;
256                     b = '-';
257                 }
258                 return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);
259             },
260             ZZ   : function () {
261                 var a = this.utcOffset(),
262                     b = '+';
263                 if (a < 0) {
264                     a = -a;
265                     b = '-';
266                 }
267                 return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
268             },
269             z : function () {
270                 return this.zoneAbbr();
271             },
272             zz : function () {
273                 return this.zoneName();
274             },
275             x    : function () {
276                 return this.valueOf();
277             },
278             X    : function () {
279                 return this.unix();
280             },
281             Q : function () {
282                 return this.quarter();
283             }
284         },
285
286         deprecations = {},
287
288         lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'],
289
290         updateInProgress = false;
291
292     // Pick the first defined of two or three arguments. dfl comes from
293     // default.
294     function dfl(a, b, c) {
295         switch (arguments.length) {
296             case 2: return a != null ? a : b;
297             case 3: return a != null ? a : b != null ? b : c;
298             default: throw new Error('Implement me');
299         }
300     }
301
302     function hasOwnProp(a, b) {
303         return hasOwnProperty.call(a, b);
304     }
305
306     function defaultParsingFlags() {
307         // We need to deep clone this object, and es5 standard is not very
308         // helpful.
309         return {
310             empty : false,
311             unusedTokens : [],
312             unusedInput : [],
313             overflow : -2,
314             charsLeftOver : 0,
315             nullInput : false,
316             invalidMonth : null,
317             invalidFormat : false,
318             userInvalidated : false,
319             iso: false
320         };
321     }
322
323     function printMsg(msg) {
324         if (moment.suppressDeprecationWarnings === false &&
325                 typeof console !== 'undefined' && console.warn) {
326             console.warn('Deprecation warning: ' + msg);
327         }
328     }
329
330     function deprecate(msg, fn) {
331         var firstTime = true;
332         return extend(function () {
333             if (firstTime) {
334                 printMsg(msg);
335                 firstTime = false;
336             }
337             return fn.apply(this, arguments);
338         }, fn);
339     }
340
341     function deprecateSimple(name, msg) {
342         if (!deprecations[name]) {
343             printMsg(msg);
344             deprecations[name] = true;
345         }
346     }
347
348     function padToken(func, count) {
349         return function (a) {
350             return leftZeroFill(func.call(this, a), count);
351         };
352     }
353     function ordinalizeToken(func, period) {
354         return function (a) {
355             return this.localeData().ordinal(func.call(this, a), period);
356         };
357     }
358
359     function monthDiff(a, b) {
360         // difference in months
361         var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
362             // b is in (anchor - 1 month, anchor + 1 month)
363             anchor = a.clone().add(wholeMonthDiff, 'months'),
364             anchor2, adjust;
365
366         if (b - anchor < 0) {
367             anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
368             // linear across the month
369             adjust = (b - anchor) / (anchor - anchor2);
370         } else {
371             anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
372             // linear across the month
373             adjust = (b - anchor) / (anchor2 - anchor);
374         }
375
376         return -(wholeMonthDiff + adjust);
377     }
378
379     while (ordinalizeTokens.length) {
380         i = ordinalizeTokens.pop();
381         formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
382     }
383     while (paddedTokens.length) {
384         i = paddedTokens.pop();
385         formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
386     }
387     formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
388
389
390     function meridiemFixWrap(locale, hour, meridiem) {
391         var isPm;
392
393         if (meridiem == null) {
394             // nothing to do
395             return hour;
396         }
397         if (locale.meridiemHour != null) {
398             return locale.meridiemHour(hour, meridiem);
399         } else if (locale.isPM != null) {
400             // Fallback
401             isPm = locale.isPM(meridiem);
402             if (isPm && hour < 12) {
403                 hour += 12;
404             }
405             if (!isPm && hour === 12) {
406                 hour = 0;
407             }
408             return hour;
409         } else {
410             // thie is not supposed to happen
411             return hour;
412         }
413     }
414
415     /************************************
416         Constructors
417     ************************************/
418
419     function Locale() {
420     }
421
422     // Moment prototype object
423     function Moment(config, skipOverflow) {
424         if (skipOverflow !== false) {
425             checkOverflow(config);
426         }
427         copyConfig(this, config);
428         this._d = new Date(+config._d);
429         // Prevent infinite loop in case updateOffset creates new moment
430         // objects.
431         if (updateInProgress === false) {
432             updateInProgress = true;
433             moment.updateOffset(this);
434             updateInProgress = false;
435         }
436     }
437
438     // Duration Constructor
439     function Duration(duration) {
440         var normalizedInput = normalizeObjectUnits(duration),
441             years = normalizedInput.year || 0,
442             quarters = normalizedInput.quarter || 0,
443             months = normalizedInput.month || 0,
444             weeks = normalizedInput.week || 0,
445             days = normalizedInput.day || 0,
446             hours = normalizedInput.hour || 0,
447             minutes = normalizedInput.minute || 0,
448             seconds = normalizedInput.second || 0,
449             milliseconds = normalizedInput.millisecond || 0;
450
451         // representation for dateAddRemove
452         this._milliseconds = +milliseconds +
453             seconds * 1e3 + // 1000
454             minutes * 6e4 + // 1000 * 60
455             hours * 36e5; // 1000 * 60 * 60
456         // Because of dateAddRemove treats 24 hours as different from a
457         // day when working around DST, we need to store them separately
458         this._days = +days +
459             weeks * 7;
460         // It is impossible translate months into days without knowing
461         // which months you are are talking about, so we have to store
462         // it separately.
463         this._months = +months +
464             quarters * 3 +
465             years * 12;
466
467         this._data = {};
468
469         this._locale = moment.localeData();
470
471         this._bubble();
472     }
473
474     /************************************
475         Helpers
476     ************************************/
477
478
479     function extend(a, b) {
480         for (var i in b) {
481             if (hasOwnProp(b, i)) {
482                 a[i] = b[i];
483             }
484         }
485
486         if (hasOwnProp(b, 'toString')) {
487             a.toString = b.toString;
488         }
489
490         if (hasOwnProp(b, 'valueOf')) {
491             a.valueOf = b.valueOf;
492         }
493
494         return a;
495     }
496
497     function copyConfig(to, from) {
498         var i, prop, val;
499
500         if (typeof from._isAMomentObject !== 'undefined') {
501             to._isAMomentObject = from._isAMomentObject;
502         }
503         if (typeof from._i !== 'undefined') {
504             to._i = from._i;
505         }
506         if (typeof from._f !== 'undefined') {
507             to._f = from._f;
508         }
509         if (typeof from._l !== 'undefined') {
510             to._l = from._l;
511         }
512         if (typeof from._strict !== 'undefined') {
513             to._strict = from._strict;
514         }
515         if (typeof from._tzm !== 'undefined') {
516             to._tzm = from._tzm;
517         }
518         if (typeof from._isUTC !== 'undefined') {
519             to._isUTC = from._isUTC;
520         }
521         if (typeof from._offset !== 'undefined') {
522             to._offset = from._offset;
523         }
524         if (typeof from._pf !== 'undefined') {
525             to._pf = from._pf;
526         }
527         if (typeof from._locale !== 'undefined') {
528             to._locale = from._locale;
529         }
530
531         if (momentProperties.length > 0) {
532             for (i in momentProperties) {
533                 prop = momentProperties[i];
534                 val = from[prop];
535                 if (typeof val !== 'undefined') {
536                     to[prop] = val;
537                 }
538             }
539         }
540
541         return to;
542     }
543
544     function absRound(number) {
545         if (number < 0) {
546             return Math.ceil(number);
547         } else {
548             return Math.floor(number);
549         }
550     }
551
552     // left zero fill a number
553     // see http://jsperf.com/left-zero-filling for performance comparison
554     function leftZeroFill(number, targetLength, forceSign) {
555         var output = '' + Math.abs(number),
556             sign = number >= 0;
557
558         while (output.length < targetLength) {
559             output = '0' + output;
560         }
561         return (sign ? (forceSign ? '+' : '') : '-') + output;
562     }
563
564     function positiveMomentsDifference(base, other) {
565         var res = {milliseconds: 0, months: 0};
566
567         res.months = other.month() - base.month() +
568             (other.year() - base.year()) * 12;
569         if (base.clone().add(res.months, 'M').isAfter(other)) {
570             --res.months;
571         }
572
573         res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
574
575         return res;
576     }
577
578     function momentsDifference(base, other) {
579         var res;
580         other = makeAs(other, base);
581         if (base.isBefore(other)) {
582             res = positiveMomentsDifference(base, other);
583         } else {
584             res = positiveMomentsDifference(other, base);
585             res.milliseconds = -res.milliseconds;
586             res.months = -res.months;
587         }
588
589         return res;
590     }
591
592     // TODO: remove 'name' arg after deprecation is removed
593     function createAdder(direction, name) {
594         return function (val, period) {
595             var dur, tmp;
596             //invert the arguments, but complain about it
597             if (period !== null && !isNaN(+period)) {
598                 deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
599                 tmp = val; val = period; period = tmp;
600             }
601
602             val = typeof val === 'string' ? +val : val;
603             dur = moment.duration(val, period);
604             addOrSubtractDurationFromMoment(this, dur, direction);
605             return this;
606         };
607     }
608
609     function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
610         var milliseconds = duration._milliseconds,
611             days = duration._days,
612             months = duration._months;
613         updateOffset = updateOffset == null ? true : updateOffset;
614
615         if (milliseconds) {
616             mom._d.setTime(+mom._d + milliseconds * isAdding);
617         }
618         if (days) {
619             rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);
620         }
621         if (months) {
622             rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);
623         }
624         if (updateOffset) {
625             moment.updateOffset(mom, days || months);
626         }
627     }
628
629     // check if is an array
630     function isArray(input) {
631         return Object.prototype.toString.call(input) === '[object Array]';
632     }
633
634     function isDate(input) {
635         return Object.prototype.toString.call(input) === '[object Date]' ||
636             input instanceof Date;
637     }
638
639     // compare two arrays, return the number of differences
640     function compareArrays(array1, array2, dontConvert) {
641         var len = Math.min(array1.length, array2.length),
642             lengthDiff = Math.abs(array1.length - array2.length),
643             diffs = 0,
644             i;
645         for (i = 0; i < len; i++) {
646             if ((dontConvert && array1[i] !== array2[i]) ||
647                 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
648                 diffs++;
649             }
650         }
651         return diffs + lengthDiff;
652     }
653
654     function normalizeUnits(units) {
655         if (units) {
656             var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
657             units = unitAliases[units] || camelFunctions[lowered] || lowered;
658         }
659         return units;
660     }
661
662     function normalizeObjectUnits(inputObject) {
663         var normalizedInput = {},
664             normalizedProp,
665             prop;
666
667         for (prop in inputObject) {
668             if (hasOwnProp(inputObject, prop)) {
669                 normalizedProp = normalizeUnits(prop);
670                 if (normalizedProp) {
671                     normalizedInput[normalizedProp] = inputObject[prop];
672                 }
673             }
674         }
675
676         return normalizedInput;
677     }
678
679     function makeList(field) {
680         var count, setter;
681
682         if (field.indexOf('week') === 0) {
683             count = 7;
684             setter = 'day';
685         }
686         else if (field.indexOf('month') === 0) {
687             count = 12;
688             setter = 'month';
689         }
690         else {
691             return;
692         }
693
694         moment[field] = function (format, index) {
695             var i, getter,
696                 method = moment._locale[field],
697                 results = [];
698
699             if (typeof format === 'number') {
700                 index = format;
701                 format = undefined;
702             }
703
704             getter = function (i) {
705                 var m = moment().utc().set(setter, i);
706                 return method.call(moment._locale, m, format || '');
707             };
708
709             if (index != null) {
710                 return getter(index);
711             }
712             else {
713                 for (i = 0; i < count; i++) {
714                     results.push(getter(i));
715                 }
716                 return results;
717             }
718         };
719     }
720
721     function toInt(argumentForCoercion) {
722         var coercedNumber = +argumentForCoercion,
723             value = 0;
724
725         if (coercedNumber !== 0 && isFinite(coercedNumber)) {
726             if (coercedNumber >= 0) {
727                 value = Math.floor(coercedNumber);
728             } else {
729                 value = Math.ceil(coercedNumber);
730             }
731         }
732
733         return value;
734     }
735
736     function daysInMonth(year, month) {
737         return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
738     }
739
740     function weeksInYear(year, dow, doy) {
741         return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;
742     }
743
744     function daysInYear(year) {
745         return isLeapYear(year) ? 366 : 365;
746     }
747
748     function isLeapYear(year) {
749         return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
750     }
751
752     function checkOverflow(m) {
753         var overflow;
754         if (m._a && m._pf.overflow === -2) {
755             overflow =
756                 m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
757                 m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
758                 m._a[HOUR] < 0 || m._a[HOUR] > 24 ||
759                     (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||
760                                            m._a[SECOND] !== 0 ||
761                                            m._a[MILLISECOND] !== 0)) ? HOUR :
762                 m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
763                 m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
764                 m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
765                 -1;
766
767             if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
768                 overflow = DATE;
769             }
770
771             m._pf.overflow = overflow;
772         }
773     }
774
775     function isValid(m) {
776         if (m._isValid == null) {
777             m._isValid = !isNaN(m._d.getTime()) &&
778                 m._pf.overflow < 0 &&
779                 !m._pf.empty &&
780                 !m._pf.invalidMonth &&
781                 !m._pf.nullInput &&
782                 !m._pf.invalidFormat &&
783                 !m._pf.userInvalidated;
784
785             if (m._strict) {
786                 m._isValid = m._isValid &&
787                     m._pf.charsLeftOver === 0 &&
788                     m._pf.unusedTokens.length === 0 &&
789                     m._pf.bigHour === undefined;
790             }
791         }
792         return m._isValid;
793     }
794
795     function normalizeLocale(key) {
796         return key ? key.toLowerCase().replace('_', '-') : key;
797     }
798
799     // pick the locale from the array
800     // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
801     // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
802     function chooseLocale(names) {
803         var i = 0, j, next, locale, split;
804
805         while (i < names.length) {
806             split = normalizeLocale(names[i]).split('-');
807             j = split.length;
808             next = normalizeLocale(names[i + 1]);
809             next = next ? next.split('-') : null;
810             while (j > 0) {
811                 locale = loadLocale(split.slice(0, j).join('-'));
812                 if (locale) {
813                     return locale;
814                 }
815                 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
816                     //the next array item is better than a shallower substring of this one
817                     break;
818                 }
819                 j--;
820             }
821             i++;
822         }
823         return null;
824     }
825
826     function loadLocale(name) {
827         var oldLocale = null;
828         if (!locales[name] && hasModule) {
829             try {
830                 oldLocale = moment.locale();
831                 require('./locale/' + name);
832                 // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales
833                 moment.locale(oldLocale);
834             } catch (e) { }
835         }
836         return locales[name];
837     }
838
839     // Return a moment from input, that is local/utc/utcOffset equivalent to
840     // model.
841     function makeAs(input, model) {
842         var res, diff;
843         if (model._isUTC) {
844             res = model.clone();
845             diff = (moment.isMoment(input) || isDate(input) ?
846                     +input : +moment(input)) - (+res);
847             // Use low-level api, because this fn is low-level api.
848             res._d.setTime(+res._d + diff);
849             moment.updateOffset(res, false);
850             return res;
851         } else {
852             return moment(input).local();
853         }
854     }
855
856     /************************************
857         Locale
858     ************************************/
859
860
861     extend(Locale.prototype, {
862
863         set : function (config) {
864             var prop, i;
865             for (i in config) {
866                 prop = config[i];
867                 if (typeof prop === 'function') {
868                     this[i] = prop;
869                 } else {
870                     this['_' + i] = prop;
871                 }
872             }
873             // Lenient ordinal parsing accepts just a number in addition to
874             // number + (possibly) stuff coming from _ordinalParseLenient.
875             this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\d{1,2}/.source);
876         },
877
878         _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
879         months : function (m) {
880             return this._months[m.month()];
881         },
882
883         _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
884         monthsShort : function (m) {
885             return this._monthsShort[m.month()];
886         },
887
888         monthsParse : function (monthName, format, strict) {
889             var i, mom, regex;
890
891             if (!this._monthsParse) {
892                 this._monthsParse = [];
893                 this._longMonthsParse = [];
894                 this._shortMonthsParse = [];
895             }
896
897             for (i = 0; i < 12; i++) {
898                 // make the regex if we don't have it already
899                 mom = moment.utc([2000, i]);
900                 if (strict && !this._longMonthsParse[i]) {
901                     this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
902                     this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
903                 }
904                 if (!strict && !this._monthsParse[i]) {
905                     regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
906                     this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
907                 }
908                 // test the regex
909                 if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
910                     return i;
911                 } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
912                     return i;
913                 } else if (!strict && this._monthsParse[i].test(monthName)) {
914                     return i;
915                 }
916             }
917         },
918
919         _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
920         weekdays : function (m) {
921             return this._weekdays[m.day()];
922         },
923
924         _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
925         weekdaysShort : function (m) {
926             return this._weekdaysShort[m.day()];
927         },
928
929         _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
930         weekdaysMin : function (m) {
931             return this._weekdaysMin[m.day()];
932         },
933
934         weekdaysParse : function (weekdayName) {
935             var i, mom, regex;
936
937             if (!this._weekdaysParse) {
938                 this._weekdaysParse = [];
939             }
940
941             for (i = 0; i < 7; i++) {
942                 // make the regex if we don't have it already
943                 if (!this._weekdaysParse[i]) {
944                     mom = moment([2000, 1]).day(i);
945                     regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
946                     this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
947                 }
948                 // test the regex
949                 if (this._weekdaysParse[i].test(weekdayName)) {
950                     return i;
951                 }
952             }
953         },
954
955         _longDateFormat : {
956             LTS : 'h:mm:ss A',
957             LT : 'h:mm A',
958             L : 'MM/DD/YYYY',
959             LL : 'MMMM D, YYYY',
960             LLL : 'MMMM D, YYYY LT',
961             LLLL : 'dddd, MMMM D, YYYY LT'
962         },
963         longDateFormat : function (key) {
964             var output = this._longDateFormat[key];
965             if (!output && this._longDateFormat[key.toUpperCase()]) {
966                 output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
967                     return val.slice(1);
968                 });
969                 this._longDateFormat[key] = output;
970             }
971             return output;
972         },
973
974         isPM : function (input) {
975             // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
976             // Using charAt should be more compatible.
977             return ((input + '').toLowerCase().charAt(0) === 'p');
978         },
979
980         _meridiemParse : /[ap]\.?m?\.?/i,
981         meridiem : function (hours, minutes, isLower) {
982             if (hours > 11) {
983                 return isLower ? 'pm' : 'PM';
984             } else {
985                 return isLower ? 'am' : 'AM';
986             }
987         },
988
989
990         _calendar : {
991             sameDay : '[Today at] LT',
992             nextDay : '[Tomorrow at] LT',
993             nextWeek : 'dddd [at] LT',
994             lastDay : '[Yesterday at] LT',
995             lastWeek : '[Last] dddd [at] LT',
996             sameElse : 'L'
997         },
998         calendar : function (key, mom, now) {
999             var output = this._calendar[key];
1000             return typeof output === 'function' ? output.apply(mom, [now]) : output;
1001         },
1002
1003         _relativeTime : {
1004             future : 'in %s',
1005             past : '%s ago',
1006             s : 'a few seconds',
1007             m : 'a minute',
1008             mm : '%d minutes',
1009             h : 'an hour',
1010             hh : '%d hours',
1011             d : 'a day',
1012             dd : '%d days',
1013             M : 'a month',
1014             MM : '%d months',
1015             y : 'a year',
1016             yy : '%d years'
1017         },
1018
1019         relativeTime : function (number, withoutSuffix, string, isFuture) {
1020             var output = this._relativeTime[string];
1021             return (typeof output === 'function') ?
1022                 output(number, withoutSuffix, string, isFuture) :
1023                 output.replace(/%d/i, number);
1024         },
1025
1026         pastFuture : function (diff, output) {
1027             var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
1028             return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
1029         },
1030
1031         ordinal : function (number) {
1032             return this._ordinal.replace('%d', number);
1033         },
1034         _ordinal : '%d',
1035         _ordinalParse : /\d{1,2}/,
1036
1037         preparse : function (string) {
1038             return string;
1039         },
1040
1041         postformat : function (string) {
1042             return string;
1043         },
1044
1045         week : function (mom) {
1046             return weekOfYear(mom, this._week.dow, this._week.doy).week;
1047         },
1048
1049         _week : {
1050             dow : 0, // Sunday is the first day of the week.
1051             doy : 6  // The week that contains Jan 1st is the first week of the year.
1052         },
1053
1054         firstDayOfWeek : function () {
1055             return this._week.dow;
1056         },
1057
1058         firstDayOfYear : function () {
1059             return this._week.doy;
1060         },
1061
1062         _invalidDate: 'Invalid date',
1063         invalidDate: function () {
1064             return this._invalidDate;
1065         }
1066     });
1067
1068     /************************************
1069         Formatting
1070     ************************************/
1071
1072
1073     function removeFormattingTokens(input) {
1074         if (input.match(/\[[\s\S]/)) {
1075             return input.replace(/^\[|\]$/g, '');
1076         }
1077         return input.replace(/\\/g, '');
1078     }
1079
1080     function makeFormatFunction(format) {
1081         var array = format.match(formattingTokens), i, length;
1082
1083         for (i = 0, length = array.length; i < length; i++) {
1084             if (formatTokenFunctions[array[i]]) {
1085                 array[i] = formatTokenFunctions[array[i]];
1086             } else {
1087                 array[i] = removeFormattingTokens(array[i]);
1088             }
1089         }
1090
1091         return function (mom) {
1092             var output = '';
1093             for (i = 0; i < length; i++) {
1094                 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
1095             }
1096             return output;
1097         };
1098     }
1099
1100     // format date using native date object
1101     function formatMoment(m, format) {
1102         if (!m.isValid()) {
1103             return m.localeData().invalidDate();
1104         }
1105
1106         format = expandFormat(format, m.localeData());
1107
1108         if (!formatFunctions[format]) {
1109             formatFunctions[format] = makeFormatFunction(format);
1110         }
1111
1112         return formatFunctions[format](m);
1113     }
1114
1115     function expandFormat(format, locale) {
1116         var i = 5;
1117
1118         function replaceLongDateFormatTokens(input) {
1119             return locale.longDateFormat(input) || input;
1120         }
1121
1122         localFormattingTokens.lastIndex = 0;
1123         while (i >= 0 && localFormattingTokens.test(format)) {
1124             format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
1125             localFormattingTokens.lastIndex = 0;
1126             i -= 1;
1127         }
1128
1129         return format;
1130     }
1131
1132
1133     /************************************
1134         Parsing
1135     ************************************/
1136
1137
1138     // get the regex to find the next token
1139     function getParseRegexForToken(token, config) {
1140         var a, strict = config._strict;
1141         switch (token) {
1142         case 'Q':
1143             return parseTokenOneDigit;
1144         case 'DDDD':
1145             return parseTokenThreeDigits;
1146         case 'YYYY':
1147         case 'GGGG':
1148         case 'gggg':
1149             return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
1150         case 'Y':
1151         case 'G':
1152         case 'g':
1153             return parseTokenSignedNumber;
1154         case 'YYYYYY':
1155         case 'YYYYY':
1156         case 'GGGGG':
1157         case 'ggggg':
1158             return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
1159         case 'S':
1160             if (strict) {
1161                 return parseTokenOneDigit;
1162             }
1163             /* falls through */
1164         case 'SS':
1165             if (strict) {
1166                 return parseTokenTwoDigits;
1167             }
1168             /* falls through */
1169         case 'SSS':
1170             if (strict) {
1171                 return parseTokenThreeDigits;
1172             }
1173             /* falls through */
1174         case 'DDD':
1175             return parseTokenOneToThreeDigits;
1176         case 'MMM':
1177         case 'MMMM':
1178         case 'dd':
1179         case 'ddd':
1180         case 'dddd':
1181             return parseTokenWord;
1182         case 'a':
1183         case 'A':
1184             return config._locale._meridiemParse;
1185         case 'x':
1186             return parseTokenOffsetMs;
1187         case 'X':
1188             return parseTokenTimestampMs;
1189         case 'Z':
1190         case 'ZZ':
1191             return parseTokenTimezone;
1192         case 'T':
1193             return parseTokenT;
1194         case 'SSSS':
1195             return parseTokenDigits;
1196         case 'MM':
1197         case 'DD':
1198         case 'YY':
1199         case 'GG':
1200         case 'gg':
1201         case 'HH':
1202         case 'hh':
1203         case 'mm':
1204         case 'ss':
1205         case 'ww':
1206         case 'WW':
1207             return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
1208         case 'M':
1209         case 'D':
1210         case 'd':
1211         case 'H':
1212         case 'h':
1213         case 'm':
1214         case 's':
1215         case 'w':
1216         case 'W':
1217         case 'e':
1218         case 'E':
1219             return parseTokenOneOrTwoDigits;
1220         case 'Do':
1221             return strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient;
1222         default :
1223             a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
1224             return a;
1225         }
1226     }
1227
1228     function utcOffsetFromString(string) {
1229         string = string || '';
1230         var possibleTzMatches = (string.match(parseTokenTimezone) || []),
1231             tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
1232             parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
1233             minutes = +(parts[1] * 60) + toInt(parts[2]);
1234
1235         return parts[0] === '+' ? minutes : -minutes;
1236     }
1237
1238     // function to convert string input to date
1239     function addTimeToArrayFromToken(token, input, config) {
1240         var a, datePartArray = config._a;
1241
1242         switch (token) {
1243         // QUARTER
1244         case 'Q':
1245             if (input != null) {
1246                 datePartArray[MONTH] = (toInt(input) - 1) * 3;
1247             }
1248             break;
1249         // MONTH
1250         case 'M' : // fall through to MM
1251         case 'MM' :
1252             if (input != null) {
1253                 datePartArray[MONTH] = toInt(input) - 1;
1254             }
1255             break;
1256         case 'MMM' : // fall through to MMMM
1257         case 'MMMM' :
1258             a = config._locale.monthsParse(input, token, config._strict);
1259             // if we didn't find a month name, mark the date as invalid.
1260             if (a != null) {
1261                 datePartArray[MONTH] = a;
1262             } else {
1263                 config._pf.invalidMonth = input;
1264             }
1265             break;
1266         // DAY OF MONTH
1267         case 'D' : // fall through to DD
1268         case 'DD' :
1269             if (input != null) {
1270                 datePartArray[DATE] = toInt(input);
1271             }
1272             break;
1273         case 'Do' :
1274             if (input != null) {
1275                 datePartArray[DATE] = toInt(parseInt(
1276                             input.match(/\d{1,2}/)[0], 10));
1277             }
1278             break;
1279         // DAY OF YEAR
1280         case 'DDD' : // fall through to DDDD
1281         case 'DDDD' :
1282             if (input != null) {
1283                 config._dayOfYear = toInt(input);
1284             }
1285
1286             break;
1287         // YEAR
1288         case 'YY' :
1289             datePartArray[YEAR] = moment.parseTwoDigitYear(input);
1290             break;
1291         case 'YYYY' :
1292         case 'YYYYY' :
1293         case 'YYYYYY' :
1294             datePartArray[YEAR] = toInt(input);
1295             break;
1296         // AM / PM
1297         case 'a' : // fall through to A
1298         case 'A' :
1299             config._meridiem = input;
1300             // config._isPm = config._locale.isPM(input);
1301             break;
1302         // HOUR
1303         case 'h' : // fall through to hh
1304         case 'hh' :
1305             config._pf.bigHour = true;
1306             /* falls through */
1307         case 'H' : // fall through to HH
1308         case 'HH' :
1309             datePartArray[HOUR] = toInt(input);
1310             break;
1311         // MINUTE
1312         case 'm' : // fall through to mm
1313         case 'mm' :
1314             datePartArray[MINUTE] = toInt(input);
1315             break;
1316         // SECOND
1317         case 's' : // fall through to ss
1318         case 'ss' :
1319             datePartArray[SECOND] = toInt(input);
1320             break;
1321         // MILLISECOND
1322         case 'S' :
1323         case 'SS' :
1324         case 'SSS' :
1325         case 'SSSS' :
1326             datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
1327             break;
1328         // UNIX OFFSET (MILLISECONDS)
1329         case 'x':
1330             config._d = new Date(toInt(input));
1331             break;
1332         // UNIX TIMESTAMP WITH MS
1333         case 'X':
1334             config._d = new Date(parseFloat(input) * 1000);
1335             break;
1336         // TIMEZONE
1337         case 'Z' : // fall through to ZZ
1338         case 'ZZ' :
1339             config._useUTC = true;
1340             config._tzm = utcOffsetFromString(input);
1341             break;
1342         // WEEKDAY - human
1343         case 'dd':
1344         case 'ddd':
1345         case 'dddd':
1346             a = config._locale.weekdaysParse(input);
1347             // if we didn't get a weekday name, mark the date as invalid
1348             if (a != null) {
1349                 config._w = config._w || {};
1350                 config._w['d'] = a;
1351             } else {
1352                 config._pf.invalidWeekday = input;
1353             }
1354             break;
1355         // WEEK, WEEK DAY - numeric
1356         case 'w':
1357         case 'ww':
1358         case 'W':
1359         case 'WW':
1360         case 'd':
1361         case 'e':
1362         case 'E':
1363             token = token.substr(0, 1);
1364             /* falls through */
1365         case 'gggg':
1366         case 'GGGG':
1367         case 'GGGGG':
1368             token = token.substr(0, 2);
1369             if (input) {
1370                 config._w = config._w || {};
1371                 config._w[token] = toInt(input);
1372             }
1373             break;
1374         case 'gg':
1375         case 'GG':
1376             config._w = config._w || {};
1377             config._w[token] = moment.parseTwoDigitYear(input);
1378         }
1379     }
1380
1381     function dayOfYearFromWeekInfo(config) {
1382         var w, weekYear, week, weekday, dow, doy, temp;
1383
1384         w = config._w;
1385         if (w.GG != null || w.W != null || w.E != null) {
1386             dow = 1;
1387             doy = 4;
1388
1389             // TODO: We need to take the current isoWeekYear, but that depends on
1390             // how we interpret now (local, utc, fixed offset). So create
1391             // a now version of current config (take local/utc/offset flags, and
1392             // create now).
1393             weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year);
1394             week = dfl(w.W, 1);
1395             weekday = dfl(w.E, 1);
1396         } else {
1397             dow = config._locale._week.dow;
1398             doy = config._locale._week.doy;
1399
1400             weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);
1401             week = dfl(w.w, 1);
1402
1403             if (w.d != null) {
1404                 // weekday -- low day numbers are considered next week
1405                 weekday = w.d;
1406                 if (weekday < dow) {
1407                     ++week;
1408                 }
1409             } else if (w.e != null) {
1410                 // local weekday -- counting starts from begining of week
1411                 weekday = w.e + dow;
1412             } else {
1413                 // default to begining of week
1414                 weekday = dow;
1415             }
1416         }
1417         temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
1418
1419         config._a[YEAR] = temp.year;
1420         config._dayOfYear = temp.dayOfYear;
1421     }
1422
1423     // convert an array to a date.
1424     // the array should mirror the parameters below
1425     // note: all values past the year are optional and will default to the lowest possible value.
1426     // [year, month, day , hour, minute, second, millisecond]
1427     function dateFromConfig(config) {
1428         var i, date, input = [], currentDate, yearToUse;
1429
1430         if (config._d) {
1431             return;
1432         }
1433
1434         currentDate = currentDateArray(config);
1435
1436         //compute day of the year from weeks and weekdays
1437         if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1438             dayOfYearFromWeekInfo(config);
1439         }
1440
1441         //if the day of the year is set, figure out what it is
1442         if (config._dayOfYear) {
1443             yearToUse = dfl(config._a[YEAR], currentDate[YEAR]);
1444
1445             if (config._dayOfYear > daysInYear(yearToUse)) {
1446                 config._pf._overflowDayOfYear = true;
1447             }
1448
1449             date = makeUTCDate(yearToUse, 0, config._dayOfYear);
1450             config._a[MONTH] = date.getUTCMonth();
1451             config._a[DATE] = date.getUTCDate();
1452         }
1453
1454         // Default to current date.
1455         // * if no year, month, day of month are given, default to today
1456         // * if day of month is given, default month and year
1457         // * if month is given, default only year
1458         // * if year is given, don't default anything
1459         for (i = 0; i < 3 && config._a[i] == null; ++i) {
1460             config._a[i] = input[i] = currentDate[i];
1461         }
1462
1463         // Zero out whatever was not defaulted, including time
1464         for (; i < 7; i++) {
1465             config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1466         }
1467
1468         // Check for 24:00:00.000
1469         if (config._a[HOUR] === 24 &&
1470                 config._a[MINUTE] === 0 &&
1471                 config._a[SECOND] === 0 &&
1472                 config._a[MILLISECOND] === 0) {
1473             config._nextDay = true;
1474             config._a[HOUR] = 0;
1475         }
1476
1477         config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
1478         // Apply timezone offset from input. The actual utcOffset can be changed
1479         // with parseZone.
1480         if (config._tzm != null) {
1481             config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
1482         }
1483
1484         if (config._nextDay) {
1485             config._a[HOUR] = 24;
1486         }
1487     }
1488
1489     function dateFromObject(config) {
1490         var normalizedInput;
1491
1492         if (config._d) {
1493             return;
1494         }
1495
1496         normalizedInput = normalizeObjectUnits(config._i);
1497         config._a = [
1498             normalizedInput.year,
1499             normalizedInput.month,
1500             normalizedInput.day || normalizedInput.date,
1501             normalizedInput.hour,
1502             normalizedInput.minute,
1503             normalizedInput.second,
1504             normalizedInput.millisecond
1505         ];
1506
1507         dateFromConfig(config);
1508     }
1509
1510     function currentDateArray(config) {
1511         var now = new Date();
1512         if (config._useUTC) {
1513             return [
1514                 now.getUTCFullYear(),
1515                 now.getUTCMonth(),
1516                 now.getUTCDate()
1517             ];
1518         } else {
1519             return [now.getFullYear(), now.getMonth(), now.getDate()];
1520         }
1521     }
1522
1523     // date from string and format string
1524     function makeDateFromStringAndFormat(config) {
1525         if (config._f === moment.ISO_8601) {
1526             parseISO(config);
1527             return;
1528         }
1529
1530         config._a = [];
1531         config._pf.empty = true;
1532
1533         // This array is used to make a Date, either with `new Date` or `Date.UTC`
1534         var string = '' + config._i,
1535             i, parsedInput, tokens, token, skipped,
1536             stringLength = string.length,
1537             totalParsedInputLength = 0;
1538
1539         tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
1540
1541         for (i = 0; i < tokens.length; i++) {
1542             token = tokens[i];
1543             parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
1544             if (parsedInput) {
1545                 skipped = string.substr(0, string.indexOf(parsedInput));
1546                 if (skipped.length > 0) {
1547                     config._pf.unusedInput.push(skipped);
1548                 }
1549                 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1550                 totalParsedInputLength += parsedInput.length;
1551             }
1552             // don't parse if it's not a known token
1553             if (formatTokenFunctions[token]) {
1554                 if (parsedInput) {
1555                     config._pf.empty = false;
1556                 }
1557                 else {
1558                     config._pf.unusedTokens.push(token);
1559                 }
1560                 addTimeToArrayFromToken(token, parsedInput, config);
1561             }
1562             else if (config._strict && !parsedInput) {
1563                 config._pf.unusedTokens.push(token);
1564             }
1565         }
1566
1567         // add remaining unparsed input length to the string
1568         config._pf.charsLeftOver = stringLength - totalParsedInputLength;
1569         if (string.length > 0) {
1570             config._pf.unusedInput.push(string);
1571         }
1572
1573         // clear _12h flag if hour is <= 12
1574         if (config._pf.bigHour === true && config._a[HOUR] <= 12) {
1575             config._pf.bigHour = undefined;
1576         }
1577         // handle meridiem
1578         config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR],
1579                 config._meridiem);
1580         dateFromConfig(config);
1581         checkOverflow(config);
1582     }
1583
1584     function unescapeFormat(s) {
1585         return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
1586             return p1 || p2 || p3 || p4;
1587         });
1588     }
1589
1590     // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1591     function regexpEscape(s) {
1592         return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1593     }
1594
1595     // date from string and array of format strings
1596     function makeDateFromStringAndArray(config) {
1597         var tempConfig,
1598             bestMoment,
1599
1600             scoreToBeat,
1601             i,
1602             currentScore;
1603
1604         if (config._f.length === 0) {
1605             config._pf.invalidFormat = true;
1606             config._d = new Date(NaN);
1607             return;
1608         }
1609
1610         for (i = 0; i < config._f.length; i++) {
1611             currentScore = 0;
1612             tempConfig = copyConfig({}, config);
1613             if (config._useUTC != null) {
1614                 tempConfig._useUTC = config._useUTC;
1615             }
1616             tempConfig._pf = defaultParsingFlags();
1617             tempConfig._f = config._f[i];
1618             makeDateFromStringAndFormat(tempConfig);
1619
1620             if (!isValid(tempConfig)) {
1621                 continue;
1622             }
1623
1624             // if there is any input that was not parsed add a penalty for that format
1625             currentScore += tempConfig._pf.charsLeftOver;
1626
1627             //or tokens
1628             currentScore += tempConfig._pf.unusedTokens.length * 10;
1629
1630             tempConfig._pf.score = currentScore;
1631
1632             if (scoreToBeat == null || currentScore < scoreToBeat) {
1633                 scoreToBeat = currentScore;
1634                 bestMoment = tempConfig;
1635             }
1636         }
1637
1638         extend(config, bestMoment || tempConfig);
1639     }
1640
1641     // date from iso format
1642     function parseISO(config) {
1643         var i, l,
1644             string = config._i,
1645             match = isoRegex.exec(string);
1646
1647         if (match) {
1648             config._pf.iso = true;
1649             for (i = 0, l = isoDates.length; i < l; i++) {
1650                 if (isoDates[i][1].exec(string)) {
1651                     // match[5] should be 'T' or undefined
1652                     config._f = isoDates[i][0] + (match[6] || ' ');
1653                     break;
1654                 }
1655             }
1656             for (i = 0, l = isoTimes.length; i < l; i++) {
1657                 if (isoTimes[i][1].exec(string)) {
1658                     config._f += isoTimes[i][0];
1659                     break;
1660                 }
1661             }
1662             if (string.match(parseTokenTimezone)) {
1663                 config._f += 'Z';
1664             }
1665             makeDateFromStringAndFormat(config);
1666         } else {
1667             config._isValid = false;
1668         }
1669     }
1670
1671     // date from iso format or fallback
1672     function makeDateFromString(config) {
1673         parseISO(config);
1674         if (config._isValid === false) {
1675             delete config._isValid;
1676             moment.createFromInputFallback(config);
1677         }
1678     }
1679
1680     function map(arr, fn) {
1681         var res = [], i;
1682         for (i = 0; i < arr.length; ++i) {
1683             res.push(fn(arr[i], i));
1684         }
1685         return res;
1686     }
1687
1688     function makeDateFromInput(config) {
1689         var input = config._i, matched;
1690         if (input === undefined) {
1691             config._d = new Date();
1692         } else if (isDate(input)) {
1693             config._d = new Date(+input);
1694         } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {
1695             config._d = new Date(+matched[1]);
1696         } else if (typeof input === 'string') {
1697             makeDateFromString(config);
1698         } else if (isArray(input)) {
1699             config._a = map(input.slice(0), function (obj) {
1700                 return parseInt(obj, 10);
1701             });
1702             dateFromConfig(config);
1703         } else if (typeof(input) === 'object') {
1704             dateFromObject(config);
1705         } else if (typeof(input) === 'number') {
1706             // from milliseconds
1707             config._d = new Date(input);
1708         } else {
1709             moment.createFromInputFallback(config);
1710         }
1711     }
1712
1713     function makeDate(y, m, d, h, M, s, ms) {
1714         //can't just apply() to create a date:
1715         //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1716         var date = new Date(y, m, d, h, M, s, ms);
1717
1718         //the date constructor doesn't accept years < 1970
1719         if (y < 1970) {
1720             date.setFullYear(y);
1721         }
1722         return date;
1723     }
1724
1725     function makeUTCDate(y) {
1726         var date = new Date(Date.UTC.apply(null, arguments));
1727         if (y < 1970) {
1728             date.setUTCFullYear(y);
1729         }
1730         return date;
1731     }
1732
1733     function parseWeekday(input, locale) {
1734         if (typeof input === 'string') {
1735             if (!isNaN(input)) {
1736                 input = parseInt(input, 10);
1737             }
1738             else {
1739                 input = locale.weekdaysParse(input);
1740                 if (typeof input !== 'number') {
1741                     return null;
1742                 }
1743             }
1744         }
1745         return input;
1746     }
1747
1748     /************************************
1749         Relative Time
1750     ************************************/
1751
1752
1753     // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
1754     function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
1755         return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
1756     }
1757
1758     function relativeTime(posNegDuration, withoutSuffix, locale) {
1759         var duration = moment.duration(posNegDuration).abs(),
1760             seconds = round(duration.as('s')),
1761             minutes = round(duration.as('m')),
1762             hours = round(duration.as('h')),
1763             days = round(duration.as('d')),
1764             months = round(duration.as('M')),
1765             years = round(duration.as('y')),
1766
1767             args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
1768                 minutes === 1 && ['m'] ||
1769                 minutes < relativeTimeThresholds.m && ['mm', minutes] ||
1770                 hours === 1 && ['h'] ||
1771                 hours < relativeTimeThresholds.h && ['hh', hours] ||
1772                 days === 1 && ['d'] ||
1773                 days < relativeTimeThresholds.d && ['dd', days] ||
1774                 months === 1 && ['M'] ||
1775                 months < relativeTimeThresholds.M && ['MM', months] ||
1776                 years === 1 && ['y'] || ['yy', years];
1777
1778         args[2] = withoutSuffix;
1779         args[3] = +posNegDuration > 0;
1780         args[4] = locale;
1781         return substituteTimeAgo.apply({}, args);
1782     }
1783
1784
1785     /************************************
1786         Week of Year
1787     ************************************/
1788
1789
1790     // firstDayOfWeek       0 = sun, 6 = sat
1791     //                      the day of the week that starts the week
1792     //                      (usually sunday or monday)
1793     // firstDayOfWeekOfYear 0 = sun, 6 = sat
1794     //                      the first week is the week that contains the first
1795     //                      of this day of the week
1796     //                      (eg. ISO weeks use thursday (4))
1797     function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
1798         var end = firstDayOfWeekOfYear - firstDayOfWeek,
1799             daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
1800             adjustedMoment;
1801
1802
1803         if (daysToDayOfWeek > end) {
1804             daysToDayOfWeek -= 7;
1805         }
1806
1807         if (daysToDayOfWeek < end - 7) {
1808             daysToDayOfWeek += 7;
1809         }
1810
1811         adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');
1812         return {
1813             week: Math.ceil(adjustedMoment.dayOfYear() / 7),
1814             year: adjustedMoment.year()
1815         };
1816     }
1817
1818     //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1819     function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1820         var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
1821
1822         d = d === 0 ? 7 : d;
1823         weekday = weekday != null ? weekday : firstDayOfWeek;
1824         daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
1825         dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
1826
1827         return {
1828             year: dayOfYear > 0 ? year : year - 1,
1829             dayOfYear: dayOfYear > 0 ?  dayOfYear : daysInYear(year - 1) + dayOfYear
1830         };
1831     }
1832
1833     /************************************
1834         Top Level Functions
1835     ************************************/
1836
1837     function makeMoment(config) {
1838         var input = config._i,
1839             format = config._f,
1840             res;
1841
1842         config._locale = config._locale || moment.localeData(config._l);
1843
1844         if (input === null || (format === undefined && input === '')) {
1845             return moment.invalid({nullInput: true});
1846         }
1847
1848         if (typeof input === 'string') {
1849             config._i = input = config._locale.preparse(input);
1850         }
1851
1852         if (moment.isMoment(input)) {
1853             return new Moment(input, true);
1854         } else if (format) {
1855             if (isArray(format)) {
1856                 makeDateFromStringAndArray(config);
1857             } else {
1858                 makeDateFromStringAndFormat(config);
1859             }
1860         } else {
1861             makeDateFromInput(config);
1862         }
1863
1864         res = new Moment(config);
1865         if (res._nextDay) {
1866             // Adding is smart enough around DST
1867             res.add(1, 'd');
1868             res._nextDay = undefined;
1869         }
1870
1871         return res;
1872     }
1873
1874     moment = function (input, format, locale, strict) {
1875         var c;
1876
1877         if (typeof(locale) === 'boolean') {
1878             strict = locale;
1879             locale = undefined;
1880         }
1881         // object construction must be done this way.
1882         // https://github.com/moment/moment/issues/1423
1883         c = {};
1884         c._isAMomentObject = true;
1885         c._i = input;
1886         c._f = format;
1887         c._l = locale;
1888         c._strict = strict;
1889         c._isUTC = false;
1890         c._pf = defaultParsingFlags();
1891
1892         return makeMoment(c);
1893     };
1894
1895     moment.suppressDeprecationWarnings = false;
1896
1897     moment.createFromInputFallback = deprecate(
1898         'moment construction falls back to js Date. This is ' +
1899         'discouraged and will be removed in upcoming major ' +
1900         'release. Please refer to ' +
1901         'https://github.com/moment/moment/issues/1407 for more info.',
1902         function (config) {
1903             config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
1904         }
1905     );
1906
1907     // Pick a moment m from moments so that m[fn](other) is true for all
1908     // other. This relies on the function fn to be transitive.
1909     //
1910     // moments should either be an array of moment objects or an array, whose
1911     // first element is an array of moment objects.
1912     function pickBy(fn, moments) {
1913         var res, i;
1914         if (moments.length === 1 && isArray(moments[0])) {
1915             moments = moments[0];
1916         }
1917         if (!moments.length) {
1918             return moment();
1919         }
1920         res = moments[0];
1921         for (i = 1; i < moments.length; ++i) {
1922             if (moments[i][fn](res)) {
1923                 res = moments[i];
1924             }
1925         }
1926         return res;
1927     }
1928
1929     moment.min = function () {
1930         var args = [].slice.call(arguments, 0);
1931
1932         return pickBy('isBefore', args);
1933     };
1934
1935     moment.max = function () {
1936         var args = [].slice.call(arguments, 0);
1937
1938         return pickBy('isAfter', args);
1939     };
1940
1941     // creating with utc
1942     moment.utc = function (input, format, locale, strict) {
1943         var c;
1944
1945         if (typeof(locale) === 'boolean') {
1946             strict = locale;
1947             locale = undefined;
1948         }
1949         // object construction must be done this way.
1950         // https://github.com/moment/moment/issues/1423
1951         c = {};
1952         c._isAMomentObject = true;
1953         c._useUTC = true;
1954         c._isUTC = true;
1955         c._l = locale;
1956         c._i = input;
1957         c._f = format;
1958         c._strict = strict;
1959         c._pf = defaultParsingFlags();
1960
1961         return makeMoment(c).utc();
1962     };
1963
1964     // creating with unix timestamp (in seconds)
1965     moment.unix = function (input) {
1966         return moment(input * 1000);
1967     };
1968
1969     // duration
1970     moment.duration = function (input, key) {
1971         var duration = input,
1972             // matching against regexp is expensive, do it on demand
1973             match = null,
1974             sign,
1975             ret,
1976             parseIso,
1977             diffRes;
1978
1979         if (moment.isDuration(input)) {
1980             duration = {
1981                 ms: input._milliseconds,
1982                 d: input._days,
1983                 M: input._months
1984             };
1985         } else if (typeof input === 'number') {
1986             duration = {};
1987             if (key) {
1988                 duration[key] = input;
1989             } else {
1990                 duration.milliseconds = input;
1991             }
1992         } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
1993             sign = (match[1] === '-') ? -1 : 1;
1994             duration = {
1995                 y: 0,
1996                 d: toInt(match[DATE]) * sign,
1997                 h: toInt(match[HOUR]) * sign,
1998                 m: toInt(match[MINUTE]) * sign,
1999                 s: toInt(match[SECOND]) * sign,
2000                 ms: toInt(match[MILLISECOND]) * sign
2001             };
2002         } else if (!!(match = isoDurationRegex.exec(input))) {
2003             sign = (match[1] === '-') ? -1 : 1;
2004             parseIso = function (inp) {
2005                 // We'd normally use ~~inp for this, but unfortunately it also
2006                 // converts floats to ints.
2007                 // inp may be undefined, so careful calling replace on it.
2008                 var res = inp && parseFloat(inp.replace(',', '.'));
2009                 // apply sign while we're at it
2010                 return (isNaN(res) ? 0 : res) * sign;
2011             };
2012             duration = {
2013                 y: parseIso(match[2]),
2014                 M: parseIso(match[3]),
2015                 d: parseIso(match[4]),
2016                 h: parseIso(match[5]),
2017                 m: parseIso(match[6]),
2018                 s: parseIso(match[7]),
2019                 w: parseIso(match[8])
2020             };
2021         } else if (duration == null) {// checks for null or undefined
2022             duration = {};
2023         } else if (typeof duration === 'object' &&
2024                 ('from' in duration || 'to' in duration)) {
2025             diffRes = momentsDifference(moment(duration.from), moment(duration.to));
2026
2027             duration = {};
2028             duration.ms = diffRes.milliseconds;
2029             duration.M = diffRes.months;
2030         }
2031
2032         ret = new Duration(duration);
2033
2034         if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {
2035             ret._locale = input._locale;
2036         }
2037
2038         return ret;
2039     };
2040
2041     // version number
2042     moment.version = VERSION;
2043
2044     // default format
2045     moment.defaultFormat = isoFormat;
2046
2047     // constant that refers to the ISO standard
2048     moment.ISO_8601 = function () {};
2049
2050     // Plugins that add properties should also add the key here (null value),
2051     // so we can properly clone ourselves.
2052     moment.momentProperties = momentProperties;
2053
2054     // This function will be called whenever a moment is mutated.
2055     // It is intended to keep the offset in sync with the timezone.
2056     moment.updateOffset = function () {};
2057
2058     // This function allows you to set a threshold for relative time strings
2059     moment.relativeTimeThreshold = function (threshold, limit) {
2060         if (relativeTimeThresholds[threshold] === undefined) {
2061             return false;
2062         }
2063         if (limit === undefined) {
2064             return relativeTimeThresholds[threshold];
2065         }
2066         relativeTimeThresholds[threshold] = limit;
2067         return true;
2068     };
2069
2070     moment.lang = deprecate(
2071         'moment.lang is deprecated. Use moment.locale instead.',
2072         function (key, value) {
2073             return moment.locale(key, value);
2074         }
2075     );
2076
2077     // This function will load locale and then set the global locale.  If
2078     // no arguments are passed in, it will simply return the current global
2079     // locale key.
2080     moment.locale = function (key, values) {
2081         var data;
2082         if (key) {
2083             if (typeof(values) !== 'undefined') {
2084                 data = moment.defineLocale(key, values);
2085             }
2086             else {
2087                 data = moment.localeData(key);
2088             }
2089
2090             if (data) {
2091                 moment.duration._locale = moment._locale = data;
2092             }
2093         }
2094
2095         return moment._locale._abbr;
2096     };
2097
2098     moment.defineLocale = function (name, values) {
2099         if (values !== null) {
2100             values.abbr = name;
2101             if (!locales[name]) {
2102                 locales[name] = new Locale();
2103             }
2104             locales[name].set(values);
2105
2106             // backwards compat for now: also set the locale
2107             moment.locale(name);
2108
2109             return locales[name];
2110         } else {
2111             // useful for testing
2112             delete locales[name];
2113             return null;
2114         }
2115     };
2116
2117     moment.langData = deprecate(
2118         'moment.langData is deprecated. Use moment.localeData instead.',
2119         function (key) {
2120             return moment.localeData(key);
2121         }
2122     );
2123
2124     // returns locale data
2125     moment.localeData = function (key) {
2126         var locale;
2127
2128         if (key && key._locale && key._locale._abbr) {
2129             key = key._locale._abbr;
2130         }
2131
2132         if (!key) {
2133             return moment._locale;
2134         }
2135
2136         if (!isArray(key)) {
2137             //short-circuit everything else
2138             locale = loadLocale(key);
2139             if (locale) {
2140                 return locale;
2141             }
2142             key = [key];
2143         }
2144
2145         return chooseLocale(key);
2146     };
2147
2148     // compare moment object
2149     moment.isMoment = function (obj) {
2150         return obj instanceof Moment ||
2151             (obj != null && hasOwnProp(obj, '_isAMomentObject'));
2152     };
2153
2154     // for typechecking Duration objects
2155     moment.isDuration = function (obj) {
2156         return obj instanceof Duration;
2157     };
2158
2159     for (i = lists.length - 1; i >= 0; --i) {
2160         makeList(lists[i]);
2161     }
2162
2163     moment.normalizeUnits = function (units) {
2164         return normalizeUnits(units);
2165     };
2166
2167     moment.invalid = function (flags) {
2168         var m = moment.utc(NaN);
2169         if (flags != null) {
2170             extend(m._pf, flags);
2171         }
2172         else {
2173             m._pf.userInvalidated = true;
2174         }
2175
2176         return m;
2177     };
2178
2179     moment.parseZone = function () {
2180         return moment.apply(null, arguments).parseZone();
2181     };
2182
2183     moment.parseTwoDigitYear = function (input) {
2184         return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
2185     };
2186
2187     moment.isDate = isDate;
2188
2189     /************************************
2190         Moment Prototype
2191     ************************************/
2192
2193
2194     extend(moment.fn = Moment.prototype, {
2195
2196         clone : function () {
2197             return moment(this);
2198         },
2199
2200         valueOf : function () {
2201             return +this._d - ((this._offset || 0) * 60000);
2202         },
2203
2204         unix : function () {
2205             return Math.floor(+this / 1000);
2206         },
2207
2208         toString : function () {
2209             return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
2210         },
2211
2212         toDate : function () {
2213             return this._offset ? new Date(+this) : this._d;
2214         },
2215
2216         toISOString : function () {
2217             var m = moment(this).utc();
2218             if (0 < m.year() && m.year() <= 9999) {
2219                 if ('function' === typeof Date.prototype.toISOString) {
2220                     // native implementation is ~50x faster, use it when we can
2221                     return this.toDate().toISOString();
2222                 } else {
2223                     return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
2224                 }
2225             } else {
2226                 return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
2227             }
2228         },
2229
2230         toArray : function () {
2231             var m = this;
2232             return [
2233                 m.year(),
2234                 m.month(),
2235                 m.date(),
2236                 m.hours(),
2237                 m.minutes(),
2238                 m.seconds(),
2239                 m.milliseconds()
2240             ];
2241         },
2242
2243         isValid : function () {
2244             return isValid(this);
2245         },
2246
2247         isDSTShifted : function () {
2248             if (this._a) {
2249                 return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
2250             }
2251
2252             return false;
2253         },
2254
2255         parsingFlags : function () {
2256             return extend({}, this._pf);
2257         },
2258
2259         invalidAt: function () {
2260             return this._pf.overflow;
2261         },
2262
2263         utc : function (keepLocalTime) {
2264             return this.utcOffset(0, keepLocalTime);
2265         },
2266
2267         local : function (keepLocalTime) {
2268             if (this._isUTC) {
2269                 this.utcOffset(0, keepLocalTime);
2270                 this._isUTC = false;
2271
2272                 if (keepLocalTime) {
2273                     this.subtract(this._dateUtcOffset(), 'm');
2274                 }
2275             }
2276             return this;
2277         },
2278
2279         format : function (inputString) {
2280             var output = formatMoment(this, inputString || moment.defaultFormat);
2281             return this.localeData().postformat(output);
2282         },
2283
2284         add : createAdder(1, 'add'),
2285
2286         subtract : createAdder(-1, 'subtract'),
2287
2288         diff : function (input, units, asFloat) {
2289             var that = makeAs(input, this),
2290                 zoneDiff = (that.utcOffset() - this.utcOffset()) * 6e4,
2291                 anchor, diff, output, daysAdjust;
2292
2293             units = normalizeUnits(units);
2294
2295             if (units === 'year' || units === 'month' || units === 'quarter') {
2296                 output = monthDiff(this, that);
2297                 if (units === 'quarter') {
2298                     output = output / 3;
2299                 } else if (units === 'year') {
2300                     output = output / 12;
2301                 }
2302             } else {
2303                 diff = this - that;
2304                 output = units === 'second' ? diff / 1e3 : // 1000
2305                     units === 'minute' ? diff / 6e4 : // 1000 * 60
2306                     units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
2307                     units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
2308                     units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
2309                     diff;
2310             }
2311             return asFloat ? output : absRound(output);
2312         },
2313
2314         from : function (time, withoutSuffix) {
2315             return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
2316         },
2317
2318         fromNow : function (withoutSuffix) {
2319             return this.from(moment(), withoutSuffix);
2320         },
2321
2322         calendar : function (time) {
2323             // We want to compare the start of today, vs this.
2324             // Getting start-of-today depends on whether we're locat/utc/offset
2325             // or not.
2326             var now = time || moment(),
2327                 sod = makeAs(now, this).startOf('day'),
2328                 diff = this.diff(sod, 'days', true),
2329                 format = diff < -6 ? 'sameElse' :
2330                     diff < -1 ? 'lastWeek' :
2331                     diff < 0 ? 'lastDay' :
2332                     diff < 1 ? 'sameDay' :
2333                     diff < 2 ? 'nextDay' :
2334                     diff < 7 ? 'nextWeek' : 'sameElse';
2335             return this.format(this.localeData().calendar(format, this, moment(now)));
2336         },
2337
2338         isLeapYear : function () {
2339             return isLeapYear(this.year());
2340         },
2341
2342         isDST : function () {
2343             return (this.utcOffset() > this.clone().month(0).utcOffset() ||
2344                 this.utcOffset() > this.clone().month(5).utcOffset());
2345         },
2346
2347         day : function (input) {
2348             var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
2349             if (input != null) {
2350                 input = parseWeekday(input, this.localeData());
2351                 return this.add(input - day, 'd');
2352             } else {
2353                 return day;
2354             }
2355         },
2356
2357         month : makeAccessor('Month', true),
2358
2359         startOf : function (units) {
2360             units = normalizeUnits(units);
2361             // the following switch intentionally omits break keywords
2362             // to utilize falling through the cases.
2363             switch (units) {
2364             case 'year':
2365                 this.month(0);
2366                 /* falls through */
2367             case 'quarter':
2368             case 'month':
2369                 this.date(1);
2370                 /* falls through */
2371             case 'week':
2372             case 'isoWeek':
2373             case 'day':
2374                 this.hours(0);
2375                 /* falls through */
2376             case 'hour':
2377                 this.minutes(0);
2378                 /* falls through */
2379             case 'minute':
2380                 this.seconds(0);
2381                 /* falls through */
2382             case 'second':
2383                 this.milliseconds(0);
2384                 /* falls through */
2385             }
2386
2387             // weeks are a special case
2388             if (units === 'week') {
2389                 this.weekday(0);
2390             } else if (units === 'isoWeek') {
2391                 this.isoWeekday(1);
2392             }
2393
2394             // quarters are also special
2395             if (units === 'quarter') {
2396                 this.month(Math.floor(this.month() / 3) * 3);
2397             }
2398
2399             return this;
2400         },
2401
2402         endOf: function (units) {
2403             units = normalizeUnits(units);
2404             if (units === undefined || units === 'millisecond') {
2405                 return this;
2406             }
2407             return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
2408         },
2409
2410         isAfter: function (input, units) {
2411             var inputMs;
2412             units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
2413             if (units === 'millisecond') {
2414                 input = moment.isMoment(input) ? input : moment(input);
2415                 return +this > +input;
2416             } else {
2417                 inputMs = moment.isMoment(input) ? +input : +moment(input);
2418                 return inputMs < +this.clone().startOf(units);
2419             }
2420         },
2421
2422         isBefore: function (input, units) {
2423             var inputMs;
2424             units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
2425             if (units === 'millisecond') {
2426                 input = moment.isMoment(input) ? input : moment(input);
2427                 return +this < +input;
2428             } else {
2429                 inputMs = moment.isMoment(input) ? +input : +moment(input);
2430                 return +this.clone().endOf(units) < inputMs;
2431             }
2432         },
2433
2434         isBetween: function (from, to, units) {
2435             return this.isAfter(from, units) && this.isBefore(to, units);
2436         },
2437
2438         isSame: function (input, units) {
2439             var inputMs;
2440             units = normalizeUnits(units || 'millisecond');
2441             if (units === 'millisecond') {
2442                 input = moment.isMoment(input) ? input : moment(input);
2443                 return +this === +input;
2444             } else {
2445                 inputMs = +moment(input);
2446                 return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
2447             }
2448         },
2449
2450         min: deprecate(
2451                  'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
2452                  function (other) {
2453                      other = moment.apply(null, arguments);
2454                      return other < this ? this : other;
2455                  }
2456          ),
2457
2458         max: deprecate(
2459                 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
2460                 function (other) {
2461                     other = moment.apply(null, arguments);
2462                     return other > this ? this : other;
2463                 }
2464         ),
2465
2466         zone : deprecate(
2467                 'moment().zone is deprecated, use moment().utcOffset instead. ' +
2468                 'https://github.com/moment/moment/issues/1779',
2469                 function (input, keepLocalTime) {
2470                     if (input != null) {
2471                         if (typeof input !== 'string') {
2472                             input = -input;
2473                         }
2474
2475                         this.utcOffset(input, keepLocalTime);
2476
2477                         return this;
2478                     } else {
2479                         return -this.utcOffset();
2480                     }
2481                 }
2482         ),
2483
2484         // keepLocalTime = true means only change the timezone, without
2485         // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
2486         // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
2487         // +0200, so we adjust the time as needed, to be valid.
2488         //
2489         // Keeping the time actually adds/subtracts (one hour)
2490         // from the actual represented time. That is why we call updateOffset
2491         // a second time. In case it wants us to change the offset again
2492         // _changeInProgress == true case, then we have to adjust, because
2493         // there is no such time in the given timezone.
2494         utcOffset : function (input, keepLocalTime) {
2495             var offset = this._offset || 0,
2496                 localAdjust;
2497             if (input != null) {
2498                 if (typeof input === 'string') {
2499                     input = utcOffsetFromString(input);
2500                 }
2501                 if (Math.abs(input) < 16) {
2502                     input = input * 60;
2503                 }
2504                 if (!this._isUTC && keepLocalTime) {
2505                     localAdjust = this._dateUtcOffset();
2506                 }
2507                 this._offset = input;
2508                 this._isUTC = true;
2509                 if (localAdjust != null) {
2510                     this.add(localAdjust, 'm');
2511                 }
2512                 if (offset !== input) {
2513                     if (!keepLocalTime || this._changeInProgress) {
2514                         addOrSubtractDurationFromMoment(this,
2515                                 moment.duration(input - offset, 'm'), 1, false);
2516                     } else if (!this._changeInProgress) {
2517                         this._changeInProgress = true;
2518                         moment.updateOffset(this, true);
2519                         this._changeInProgress = null;
2520                     }
2521                 }
2522
2523                 return this;
2524             } else {
2525                 return this._isUTC ? offset : this._dateUtcOffset();
2526             }
2527         },
2528
2529         isLocal : function () {
2530             return !this._isUTC;
2531         },
2532
2533         isUtcOffset : function () {
2534             return this._isUTC;
2535         },
2536
2537         isUtc : function () {
2538             return this._isUTC && this._offset === 0;
2539         },
2540
2541         zoneAbbr : function () {
2542             return this._isUTC ? 'UTC' : '';
2543         },
2544
2545         zoneName : function () {
2546             return this._isUTC ? 'Coordinated Universal Time' : '';
2547         },
2548
2549         parseZone : function () {
2550             if (this._tzm) {
2551                 this.utcOffset(this._tzm);
2552             } else if (typeof this._i === 'string') {
2553                 this.utcOffset(utcOffsetFromString(this._i));
2554             }
2555             return this;
2556         },
2557
2558         hasAlignedHourOffset : function (input) {
2559             if (!input) {
2560                 input = 0;
2561             }
2562             else {
2563                 input = moment(input).utcOffset();
2564             }
2565
2566             return (this.utcOffset() - input) % 60 === 0;
2567         },
2568
2569         daysInMonth : function () {
2570             return daysInMonth(this.year(), this.month());
2571         },
2572
2573         dayOfYear : function (input) {
2574             var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
2575             return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
2576         },
2577
2578         quarter : function (input) {
2579             return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
2580         },
2581
2582         weekYear : function (input) {
2583             var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
2584             return input == null ? year : this.add((input - year), 'y');
2585         },
2586
2587         isoWeekYear : function (input) {
2588             var year = weekOfYear(this, 1, 4).year;
2589             return input == null ? year : this.add((input - year), 'y');
2590         },
2591
2592         week : function (input) {
2593             var week = this.localeData().week(this);
2594             return input == null ? week : this.add((input - week) * 7, 'd');
2595         },
2596
2597         isoWeek : function (input) {
2598             var week = weekOfYear(this, 1, 4).week;
2599             return input == null ? week : this.add((input - week) * 7, 'd');
2600         },
2601
2602         weekday : function (input) {
2603             var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
2604             return input == null ? weekday : this.add(input - weekday, 'd');
2605         },
2606
2607         isoWeekday : function (input) {
2608             // behaves the same as moment#day except
2609             // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
2610             // as a setter, sunday should belong to the previous week.
2611             return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
2612         },
2613
2614         isoWeeksInYear : function () {
2615             return weeksInYear(this.year(), 1, 4);
2616         },
2617
2618         weeksInYear : function () {
2619             var weekInfo = this.localeData()._week;
2620             return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
2621         },
2622
2623         get : function (units) {
2624             units = normalizeUnits(units);
2625             return this[units]();
2626         },
2627
2628         set : function (units, value) {
2629             var unit;
2630             if (typeof units === 'object') {
2631                 for (unit in units) {
2632                     this.set(unit, units[unit]);
2633                 }
2634             }
2635             else {
2636                 units = normalizeUnits(units);
2637                 if (typeof this[units] === 'function') {
2638                     this[units](value);
2639                 }
2640             }
2641             return this;
2642         },
2643
2644         // If passed a locale key, it will set the locale for this
2645         // instance.  Otherwise, it will return the locale configuration
2646         // variables for this instance.
2647         locale : function (key) {
2648             var newLocaleData;
2649
2650             if (key === undefined) {
2651                 return this._locale._abbr;
2652             } else {
2653                 newLocaleData = moment.localeData(key);
2654                 if (newLocaleData != null) {
2655                     this._locale = newLocaleData;
2656                 }
2657                 return this;
2658             }
2659         },
2660
2661         lang : deprecate(
2662             'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
2663             function (key) {
2664                 if (key === undefined) {
2665                     return this.localeData();
2666                 } else {
2667                     return this.locale(key);
2668                 }
2669             }
2670         ),
2671
2672         localeData : function () {
2673             return this._locale;
2674         },
2675
2676         _dateUtcOffset : function () {
2677             // On Firefox.24 Date#getTimezoneOffset returns a floating point.
2678             // https://github.com/moment/moment/pull/1871
2679             return -Math.round(this._d.getTimezoneOffset() / 15) * 15;
2680         }
2681
2682     });
2683
2684     function rawMonthSetter(mom, value) {
2685         var dayOfMonth;
2686
2687         // TODO: Move this out of here!
2688         if (typeof value === 'string') {
2689             value = mom.localeData().monthsParse(value);
2690             // TODO: Another silent failure?
2691             if (typeof value !== 'number') {
2692                 return mom;
2693             }
2694         }
2695
2696         dayOfMonth = Math.min(mom.date(),
2697                 daysInMonth(mom.year(), value));
2698         mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
2699         return mom;
2700     }
2701
2702     function rawGetter(mom, unit) {
2703         return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();
2704     }
2705
2706     function rawSetter(mom, unit, value) {
2707         if (unit === 'Month') {
2708             return rawMonthSetter(mom, value);
2709         } else {
2710             return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
2711         }
2712     }
2713
2714     function makeAccessor(unit, keepTime) {
2715         return function (value) {
2716             if (value != null) {
2717                 rawSetter(this, unit, value);
2718                 moment.updateOffset(this, keepTime);
2719                 return this;
2720             } else {
2721                 return rawGetter(this, unit);
2722             }
2723         };
2724     }
2725
2726     moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false);
2727     moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false);
2728     moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false);
2729     // Setting the hour should keep the time, because the user explicitly
2730     // specified which hour he wants. So trying to maintain the same hour (in
2731     // a new timezone) makes sense. Adding/subtracting hours does not follow
2732     // this rule.
2733     moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true);
2734     // moment.fn.month is defined separately
2735     moment.fn.date = makeAccessor('Date', true);
2736     moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true));
2737     moment.fn.year = makeAccessor('FullYear', true);
2738     moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true));
2739
2740     // add plural methods
2741     moment.fn.days = moment.fn.day;
2742     moment.fn.months = moment.fn.month;
2743     moment.fn.weeks = moment.fn.week;
2744     moment.fn.isoWeeks = moment.fn.isoWeek;
2745     moment.fn.quarters = moment.fn.quarter;
2746
2747     // add aliased format methods
2748     moment.fn.toJSON = moment.fn.toISOString;
2749
2750     // alias isUtc for dev-friendliness
2751     moment.fn.isUTC = moment.fn.isUtc;
2752
2753     /************************************
2754         Duration Prototype
2755     ************************************/
2756
2757
2758     function daysToYears (days) {
2759         // 400 years have 146097 days (taking into account leap year rules)
2760         return days * 400 / 146097;
2761     }
2762
2763     function yearsToDays (years) {
2764         // years * 365 + absRound(years / 4) -
2765         //     absRound(years / 100) + absRound(years / 400);
2766         return years * 146097 / 400;
2767     }
2768
2769     extend(moment.duration.fn = Duration.prototype, {
2770
2771         _bubble : function () {
2772             var milliseconds = this._milliseconds,
2773                 days = this._days,
2774                 months = this._months,
2775                 data = this._data,
2776                 seconds, minutes, hours, years = 0;
2777
2778             // The following code bubbles up values, see the tests for
2779             // examples of what that means.
2780             data.milliseconds = milliseconds % 1000;
2781
2782             seconds = absRound(milliseconds / 1000);
2783             data.seconds = seconds % 60;
2784
2785             minutes = absRound(seconds / 60);
2786             data.minutes = minutes % 60;
2787
2788             hours = absRound(minutes / 60);
2789             data.hours = hours % 24;
2790
2791             days += absRound(hours / 24);
2792
2793             // Accurately convert days to years, assume start from year 0.
2794             years = absRound(daysToYears(days));
2795             days -= absRound(yearsToDays(years));
2796
2797             // 30 days to a month
2798             // TODO (iskren): Use anchor date (like 1st Jan) to compute this.
2799             months += absRound(days / 30);
2800             days %= 30;
2801
2802             // 12 months -> 1 year
2803             years += absRound(months / 12);
2804             months %= 12;
2805
2806             data.days = days;
2807             data.months = months;
2808             data.years = years;
2809         },
2810
2811         abs : function () {
2812             this._milliseconds = Math.abs(this._milliseconds);
2813             this._days = Math.abs(this._days);
2814             this._months = Math.abs(this._months);
2815
2816             this._data.milliseconds = Math.abs(this._data.milliseconds);
2817             this._data.seconds = Math.abs(this._data.seconds);
2818             this._data.minutes = Math.abs(this._data.minutes);
2819             this._data.hours = Math.abs(this._data.hours);
2820             this._data.months = Math.abs(this._data.months);
2821             this._data.years = Math.abs(this._data.years);
2822
2823             return this;
2824         },
2825
2826         weeks : function () {
2827             return absRound(this.days() / 7);
2828         },
2829
2830         valueOf : function () {
2831             return this._milliseconds +
2832               this._days * 864e5 +
2833               (this._months % 12) * 2592e6 +
2834               toInt(this._months / 12) * 31536e6;
2835         },
2836
2837         humanize : function (withSuffix) {
2838             var output = relativeTime(this, !withSuffix, this.localeData());
2839
2840             if (withSuffix) {
2841                 output = this.localeData().pastFuture(+this, output);
2842             }
2843
2844             return this.localeData().postformat(output);
2845         },
2846
2847         add : function (input, val) {
2848             // supports only 2.0-style add(1, 's') or add(moment)
2849             var dur = moment.duration(input, val);
2850
2851             this._milliseconds += dur._milliseconds;
2852             this._days += dur._days;
2853             this._months += dur._months;
2854
2855             this._bubble();
2856
2857             return this;
2858         },
2859
2860         subtract : function (input, val) {
2861             var dur = moment.duration(input, val);
2862
2863             this._milliseconds -= dur._milliseconds;
2864             this._days -= dur._days;
2865             this._months -= dur._months;
2866
2867             this._bubble();
2868
2869             return this;
2870         },
2871
2872         get : function (units) {
2873             units = normalizeUnits(units);
2874             return this[units.toLowerCase() + 's']();
2875         },
2876
2877         as : function (units) {
2878             var days, months;
2879             units = normalizeUnits(units);
2880
2881             if (units === 'month' || units === 'year') {
2882                 days = this._days + this._milliseconds / 864e5;
2883                 months = this._months + daysToYears(days) * 12;
2884                 return units === 'month' ? months : months / 12;
2885             } else {
2886                 // handle milliseconds separately because of floating point math errors (issue #1867)
2887                 days = this._days + Math.round(yearsToDays(this._months / 12));
2888                 switch (units) {
2889                     case 'week': return days / 7 + this._milliseconds / 6048e5;
2890                     case 'day': return days + this._milliseconds / 864e5;
2891                     case 'hour': return days * 24 + this._milliseconds / 36e5;
2892                     case 'minute': return days * 24 * 60 + this._milliseconds / 6e4;
2893                     case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000;
2894                     // Math.floor prevents floating point math errors here
2895                     case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds;
2896                     default: throw new Error('Unknown unit ' + units);
2897                 }
2898             }
2899         },
2900
2901         lang : moment.fn.lang,
2902         locale : moment.fn.locale,
2903
2904         toIsoString : deprecate(
2905             'toIsoString() is deprecated. Please use toISOString() instead ' +
2906             '(notice the capitals)',
2907             function () {
2908                 return this.toISOString();
2909             }
2910         ),
2911
2912         toISOString : function () {
2913             // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
2914             var years = Math.abs(this.years()),
2915                 months = Math.abs(this.months()),
2916                 days = Math.abs(this.days()),
2917                 hours = Math.abs(this.hours()),
2918                 minutes = Math.abs(this.minutes()),
2919                 seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
2920
2921             if (!this.asSeconds()) {
2922                 // this is the same as C#'s (Noda) and python (isodate)...
2923                 // but not other JS (goog.date)
2924                 return 'P0D';
2925             }
2926
2927             return (this.asSeconds() < 0 ? '-' : '') +
2928                 'P' +
2929                 (years ? years + 'Y' : '') +
2930                 (months ? months + 'M' : '') +
2931                 (days ? days + 'D' : '') +
2932                 ((hours || minutes || seconds) ? 'T' : '') +
2933                 (hours ? hours + 'H' : '') +
2934                 (minutes ? minutes + 'M' : '') +
2935                 (seconds ? seconds + 'S' : '');
2936         },
2937
2938         localeData : function () {
2939             return this._locale;
2940         },
2941
2942         toJSON : function () {
2943             return this.toISOString();
2944         }
2945     });
2946
2947     moment.duration.fn.toString = moment.duration.fn.toISOString;
2948
2949     function makeDurationGetter(name) {
2950         moment.duration.fn[name] = function () {
2951             return this._data[name];
2952         };
2953     }
2954
2955     for (i in unitMillisecondFactors) {
2956         if (hasOwnProp(unitMillisecondFactors, i)) {
2957             makeDurationGetter(i.toLowerCase());
2958         }
2959     }
2960
2961     moment.duration.fn.asMilliseconds = function () {
2962         return this.as('ms');
2963     };
2964     moment.duration.fn.asSeconds = function () {
2965         return this.as('s');
2966     };
2967     moment.duration.fn.asMinutes = function () {
2968         return this.as('m');
2969     };
2970     moment.duration.fn.asHours = function () {
2971         return this.as('h');
2972     };
2973     moment.duration.fn.asDays = function () {
2974         return this.as('d');
2975     };
2976     moment.duration.fn.asWeeks = function () {
2977         return this.as('weeks');
2978     };
2979     moment.duration.fn.asMonths = function () {
2980         return this.as('M');
2981     };
2982     moment.duration.fn.asYears = function () {
2983         return this.as('y');
2984     };
2985
2986     /************************************
2987         Default Locale
2988     ************************************/
2989
2990
2991     // Set default locale, other locale will inherit from English.
2992     moment.locale('en', {
2993         ordinalParse: /\d{1,2}(th|st|nd|rd)/,
2994         ordinal : function (number) {
2995             var b = number % 10,
2996                 output = (toInt(number % 100 / 10) === 1) ? 'th' :
2997                 (b === 1) ? 'st' :
2998                 (b === 2) ? 'nd' :
2999                 (b === 3) ? 'rd' : 'th';
3000             return number + output;
3001         }
3002     });
3003
3004     /* EMBED_LOCALES */
3005
3006     /************************************
3007         Exposing Moment
3008     ************************************/
3009
3010     function makeGlobal(shouldDeprecate) {
3011         /*global ender:false */
3012         if (typeof ender !== 'undefined') {
3013             return;
3014         }
3015         oldGlobalMoment = globalScope.moment;
3016         if (shouldDeprecate) {
3017             globalScope.moment = deprecate(
3018                     'Accessing Moment through the global scope is ' +
3019                     'deprecated, and will be removed in an upcoming ' +
3020                     'release.',
3021                     moment);
3022         } else {
3023             globalScope.moment = moment;
3024         }
3025     }
3026
3027     // CommonJS module is defined
3028     if (hasModule) {
3029         module.exports = moment;
3030     } else if (typeof define === 'function' && define.amd) {
3031         define(function (require, exports, module) {
3032             if (module.config && module.config() && module.config().noGlobal === true) {
3033                 // release the global variable
3034                 globalScope.moment = oldGlobalMoment;
3035             }
3036
3037             return moment;
3038         });
3039         makeGlobal(true);
3040     } else {
3041         makeGlobal();
3042     }
3043 }).call(this);