PageSourceSearch

https://app.vidnoz.com/static/dist/js/moment.min.js

js vidnoz.com collected 2026-09-24 09:21:46 UTC 73,214 bytes, 2,400 lines download raw bytes

1//! moment.js
2//! version : 2.5.1
3//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4//! license : MIT
5//! momentjs.com
6
7(function (undefined) {
8
9  /************************************
10      Constants
11  ************************************/
12
13  var moment,
14      VERSION = "2.5.1",
15      global = this,
16      round = Math.round,
17      i,
18
19      YEAR = 0,
20      MONTH = 1,
21      DATE = 2,
22      HOUR = 3,
23      MINUTE = 4,
24      SECOND = 5,
25      MILLISECOND = 6,
26
27      // internal storage for language config files
28      languages = {},
29
30      // moment internal properties
31      momentProperties = {
32          _isAMomentObject: null,
33          _i : null,
34          _f : null,
35          _l : null,
36          _strict : null,
37          _isUTC : null,
38          _offset : null,  // optional. Combine with _isUTC
39          _pf : null,
40          _lang : null  // optional
41      },
42
43      // check for nodeJS
44      hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
45
46      // ASP.NET json date format regex
47      aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
48      aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
49
50      // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
51      // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
52      isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
53
54      // format tokens
55      formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
56      localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
57
58      // parsing token regexes
59      parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
60      parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
61      parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
62      parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
63      parseTokenDigits = /\d+/, // nonzero number of digits
64      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.
65      parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
66      parseTokenT = /T/i, // T (ISO separator)
67      parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
68
69      //strict parsing regexes
70      parseTokenOneDigit = /\d/, // 0 - 9
71      parseTokenTwoDigits = /\d\d/, // 00 - 99
72      parseTokenThreeDigits = /\d{3}/, // 000 - 999
73      parseTokenFourDigits = /\d{4}/, // 0000 - 9999
74      parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
75      parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
76
77      // iso 8601 regex
78      // 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)
79      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)?)?$/,
80
81      isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
82
83      isoDates = [
84          ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
85          ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
86          ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
87          ['GGGG-[W]WW', /\d{4}-W\d{2}/],
88          ['YYYY-DDD', /\d{4}-\d{3}/]
89      ],
90
91      // iso time formats and regexes
92      isoTimes = [
93          ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
94          ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
95          ['HH:mm', /(T| )\d\d:\d\d/],
96          ['HH', /(T| )\d\d/]
97      ],
98
99      // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
100      parseTimezoneChunker = /([\+\-]|\d\d)/gi,
101
102      // getter and setter names
103      proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
104      unitMillisecondFactors = {
105          'Milliseconds' : 1,
106          'Seconds' : 1e3,
107          'Minutes' : 6e4,
108          'Hours' : 36e5,
109          'Days' : 864e5,
110          'Months' : 2592e6,
111          'Years' : 31536e6
112      },
113
114      unitAliases = {
115          ms : 'millisecond',
116          s : 'second',
117          m : 'minute',
118          h : 'hour',
119          d : 'day',
120          D : 'date',
121          w : 'week',
122          W : 'isoWeek',
123          M : 'month',
124          y : 'year',
125          DDD : 'dayOfYear',
126          e : 'weekday',
127          E : 'isoWeekday',
128          gg: 'weekYear',
129          GG: 'isoWeekYear'
130      },
131
132      camelFunctions = {
133          dayofyear : 'dayOfYear',
134          isoweekday : 'isoWeekday',
135          isoweek : 'isoWeek',
136          weekyear : 'weekYear',
137          isoweekyear : 'isoWeekYear'
138      },
139
140      // format function strings
141      formatFunctions = {},
142
143      // tokens to ordinalize and pad
144      ordinalizeTokens = 'DDD w W M D d'.split(' '),
145      paddedTokens = 'M D H h m s w W'.split(' '),
146
147      formatTokenFunctions = {
148          M    : function () {
149              return this.month() + 1;
150          },
151          MMM  : function (format) {
152              return this.lang().monthsShort(this, format);
153          },
154          MMMM : function (format) {
155              return this.lang().months(this, format);
156          },
157          D    : function () {
158              return this.date();
159          },
160          DDD  : function () {
161              return this.dayOfYear();
162          },
163          d    : function () {
164              return this.day();
165          },
166          dd   : function (format) {
167              return this.lang().weekdaysMin(this, format);
168          },
169          ddd  : function (format) {
170              return this.lang().weekdaysShort(this, format);
171          },
172          dddd : function (format) {
173              return this.lang().weekdays(this, format);
174          },
175          w    : function () {
176              return this.week();
177          },
178          W    : function () {
179              return this.isoWeek();
180          },
181          YY   : function () {
182              return leftZeroFill(this.year() % 100, 2);
183          },
184          YYYY : function () {
185              return leftZeroFill(this.year(), 4);
186          },
187          YYYYY : function () {
188              return leftZeroFill(this.year(), 5);
189          },
190          YYYYYY : function () {
191              var y = this.year(), sign = y >= 0 ? '+' : '-';
192              return sign + leftZeroFill(Math.abs(y), 6);
193          },
194          gg   : function () {
195              return leftZeroFill(this.weekYear() % 100, 2);
196          },
197          gggg : function () {
198              return leftZeroFill(this.weekYear(), 4);
199          },
200          ggggg : function () {
201              return leftZeroFill(this.weekYear(), 5);
202          },
203          GG   : function () {
204              return leftZeroFill(this.isoWeekYear() % 100, 2);
205          },
206          GGGG : function () {
207              return leftZeroFill(this.isoWeekYear(), 4);
208          },
209          GGGGG : function () {
210              return leftZeroFill(this.isoWeekYear(), 5);
211          },
212          e : function () {
213              return this.weekday();
214          },
215          E : function () {
216              return this.isoWeekday();
217          },
218          a    : function () {
219              return this.lang().meridiem(this.hours(), this.minutes(), true);
220          },
221          A    : function () {
222              return this.lang().meridiem(this.hours(), this.minutes(), false);
223          },
224          H    : function () {
225              return this.hours();
226          },
227          h    : function () {
228              return this.hours() % 12 || 12;
229          },
230          m    : function () {
231              return this.minutes();
232          },
233          s    : function () {
234              return this.seconds();
235          },
236          S    : function () {
237              return toInt(this.milliseconds() / 100);
238          },
239          SS   : function () {
240              return leftZeroFill(toInt(this.milliseconds() / 10), 2);
241          },
242          SSS  : function () {
243              return leftZeroFill(this.milliseconds(), 3);
244          },
245          SSSS : function () {
246              return leftZeroFill(this.milliseconds(), 3);
247          },
248          Z    : function () {
249              var a = -this.zone(),
250                  b = "+";
251              if (a < 0) {
252                  a = -a;
253                  b = "-";
254              }
255              return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
256          },
257          ZZ   : function () {
258              var a = -this.zone(),
259                  b = "+";
260              if (a < 0) {
261                  a = -a;
262                  b = "-";
263              }
264              return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
265          },
266          z : function () {
267              return this.zoneAbbr();
268          },
269          zz : function () {
270              return this.zoneName();
271          },
272          X    : function () {
273              return this.unix();
274          },
275          Q : function () {
276              return this.quarter();
277          }
278      },
279
280      lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
281
282  function defaultParsingFlags() {
283      // We need to deep clone this object, and es5 standard is not very
284      // helpful.
285      return {
286          empty : false,
287          unusedTokens : [],
288          unusedInput : [],
289          overflow : -2,
290          charsLeftOver : 0,
291          nullInput : false,
292          invalidMonth : null,
293          invalidFormat : false,
294          userInvalidated : false,
295          iso: false
296      };
297  }
298
299  function padToken(func, count) {
300      return function (a) {
301          return leftZeroFill(func.call(this, a), count);
302      };
303  }
304  function ordinalizeToken(func, period) {
305      return function (a) {
306          return this.lang().ordinal(func.call(this, a), period);
307      };
308  }
309
310  while (ordinalizeTokens.length) {
311      i = ordinalizeTokens.pop();
312      formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
313  }
314  while (paddedTokens.length) {
315      i = paddedTokens.pop();
316      formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
317  }
318  formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
319
320
321  /************************************
322      Constructors
323  ************************************/
324
325  function Language() {
326
327  }
328
329  // Moment prototype object
330  function Moment(config) {
331      checkOverflow(config);
332      extend(this, config);
333  }
334
335  // Duration Constructor
336  function Duration(duration) {
337      var normalizedInput = normalizeObjectUnits(duration),
338          years = normalizedInput.year || 0,
339          months = normalizedInput.month || 0,
340          weeks = normalizedInput.week || 0,
341          days = normalizedInput.day || 0,
342          hours = normalizedInput.hour || 0,
343          minutes = normalizedInput.minute || 0,
344          seconds = normalizedInput.second || 0,
345          milliseconds = normalizedInput.millisecond || 0;
346
347      // representation for dateAddRemove
348      this._milliseconds = +milliseconds +
349          seconds * 1e3 + // 1000
350          minutes * 6e4 + // 1000 * 60
351          hours * 36e5; // 1000 * 60 * 60
352      // Because of dateAddRemove treats 24 hours as different from a
353      // day when working around DST, we need to store them separately
354      this._days = +days +
355          weeks * 7;
356      // It is impossible translate months into days without knowing
357      // which months you are are talking about, so we have to store
358      // it separately.
359      this._months = +months +
360          years * 12;
361
362      this._data = {};
363
364      this._bubble();
365  }
366
367  /************************************
368      Helpers
369  ************************************/
370
371
372  function extend(a, b) {
373      for (var i in b) {
374          if (b.hasOwnProperty(i)) {
375              a[i] = b[i];
376          }
377      }
378
379      if (b.hasOwnProperty("toString")) {
380          a.toString = b.toString;
381      }
382
383      if (b.hasOwnProperty("valueOf")) {
384          a.valueOf = b.valueOf;
385      }
386
387      return a;
388  }
389
390  function cloneMoment(m) {
391      var result = {}, i;
392      for (i in m) {
393          if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) {
394              result[i] = m[i];
395          }
396      }
397
398      return result;
399  }
400
401  function absRound(number) {
402      if (number < 0) {
403          return Math.ceil(number);
404      } else {
405          return Math.floor(number);
406      }
407  }
408
409  // left zero fill a number
410  // see http://jsperf.com/left-zero-filling for performance comparison
411  function leftZeroFill(number, targetLength, forceSign) {
412      var output = '' + Math.abs(number),
413          sign = number >= 0;
414
415      while (output.length < targetLength) {
416          output = '0' + output;
417      }
418      return (sign ? (forceSign ? '+' : '') : '-') + output;
419  }
420
421  // helper function for _.addTime and _.subtractTime
422  function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
423      var milliseconds = duration._milliseconds,
424          days = duration._days,
425          months = duration._months,
426          minutes,
427          hours;
428
429      if (milliseconds) {
430          mom._d.setTime(+mom._d + milliseconds * isAdding);
431      }
432      // store the minutes and hours so we can restore them
433      if (days || months) {
434          minutes = mom.minute();
435          hours = mom.hour();
436      }
437      if (days) {
438          mom.date(mom.date() + days * isAdding);
439      }
440      if (months) {
441          mom.month(mom.month() + months * isAdding);
442      }
443      if (milliseconds && !ignoreUpdateOffset) {
444          moment.updateOffset(mom);
445      }
446      // restore the minutes and hours after possibly changing dst
447      if (days || months) {
448          mom.minute(minutes);
449          mom.hour(hours);
450      }
451  }
452
453  // check if is an array
454  function isArray(input) {
455      return Object.prototype.toString.call(input) === '[object Array]';
456  }
457
458  function isDate(input) {
459      return  Object.prototype.toString.call(input) === '[object Date]' ||
460              input instanceof Date;
461  }
462
463  // compare two arrays, return the number of differences
464  function compareArrays(array1, array2, dontConvert) {
465      var len = Math.min(array1.length, array2.length),
466          lengthDiff = Math.abs(array1.length - array2.length),
467          diffs = 0,
468          i;
469      for (i = 0; i < len; i++) {
470          if ((dontConvert && array1[i] !== array2[i]) ||
471              (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
472              diffs++;
473          }
474      }
475      return diffs + lengthDiff;
476  }
477
478  function normalizeUnits(units) {
479      if (units) {
480          var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
481          units = unitAliases[units] || camelFunctions[lowered] || lowered;
482      }
483      return units;
484  }
485
486  function normalizeObjectUnits(inputObject) {
487      var normalizedInput = {},
488          normalizedProp,
489          prop;
490
491      for (prop in inputObject) {
492          if (inputObject.hasOwnProperty(prop)) {
493              normalizedProp = normalizeUnits(prop);
494              if (normalizedProp) {
495                  normalizedInput[normalizedProp] = inputObject[prop];
496              }
497          }
498      }
499
500      return normalizedInput;
501  }
502
503  function makeList(field) {
504      var count, setter;
505
506      if (field.indexOf('week') === 0) {
507          count = 7;
508          setter = 'day';
509      }
510      else if (field.indexOf('month') === 0) {
511          count = 12;
512          setter = 'month';
513      }
514      else {
515          return;
516      }
517
518      moment[field] = function (format, index) {
519          var i, getter,
520              method = moment.fn._lang[field],
521              results = [];
522
523          if (typeof format === 'number') {
524              index = format;
525              format = undefined;
526          }
527
528          getter = function (i) {
529              var m = moment().utc().set(setter, i);
530              return method.call(moment.fn._lang, m, format || '');
531          };
532
533          if (index != null) {
534              return getter(index);
535          }
536          else {
537              for (i = 0; i < count; i++) {
538                  results.push(getter(i));
539              }
540              return results;
541          }
542      };
543  }
544
545  function toInt(argumentForCoercion) {
546      var coercedNumber = +argumentForCoercion,
547          value = 0;
548
549      if (coercedNumber !== 0 && isFinite(coercedNumber)) {
550          if (coercedNumber >= 0) {
551              value = Math.floor(coercedNumber);
552          } else {
553              value = Math.ceil(coercedNumber);
554          }
555      }
556
557      return value;
558  }
559
560  function daysInMonth(year, month) {
561      return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
562  }
563
564  function daysInYear(year) {
565      return isLeapYear(year) ? 366 : 365;
566  }
567
568  function isLeapYear(year) {
569      return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
570  }
571
572  function checkOverflow(m) {
573      var overflow;
574      if (m._a && m._pf.overflow === -2) {
575          overflow =
576              m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
577              m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
578              m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
579              m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
580              m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
581              m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
582              -1;
583
584          if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
585              overflow = DATE;
586          }
587
588          m._pf.overflow = overflow;
589      }
590  }
591
592  function isValid(m) {
593      if (m._isValid == null) {
594          m._isValid = !isNaN(m._d.getTime()) &&
595              m._pf.overflow < 0 &&
596              !m._pf.empty &&
597              !m._pf.invalidMonth &&
598              !m._pf.nullInput &&
599              !m._pf.invalidFormat &&
600              !m._pf.userInvalidated;
601
602          if (m._strict) {
603              m._isValid = m._isValid &&
604                  m._pf.charsLeftOver === 0 &&
605                  m._pf.unusedTokens.length === 0;
606          }
607      }
608      return m._isValid;
609  }
610
611  function normalizeLanguage(key) {
612      return key ? key.toLowerCase().replace('_', '-') : key;
613  }
614
615  // Return a moment from input, that is local/utc/zone equivalent to model.
616  function makeAs(input, model) {
617      return model._isUTC ? moment(input).zone(model._offset || 0) :
618          moment(input).local();
619  }
620
621  /************************************
622      Languages
623  ************************************/
624
625
626  extend(Language.prototype, {
627
628      set : function (config) {
629          var prop, i;
630          for (i in config) {
631              prop = config[i];
632              if (typeof prop === 'function') {
633                  this[i] = prop;
634              } else {
635                  this['_' + i] = prop;
636              }
637          }
638      },
639
640      _months: "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
641      months : function (m) {
642          return this._months[m.month()];
643      },
644
645      _monthsShort : "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),
646      monthsShort : function (m) {
647          return this._monthsShort[m.month()];
648      },
649
650      monthsParse : function (monthName) {
651          var i, mom, regex;
652
653          if (!this._monthsParse) {
654              this._monthsParse = [];
655          }
656
657          for (i = 0; i < 12; i++) {
658              // make the regex if we don't have it already
659              if (!this._monthsParse[i]) {
660                  mom = moment.utc([2000, i]);
661                  regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
662                  this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
663              }
664              // test the regex
665              if (this._monthsParse[i].test(monthName)) {
666                  return i;
667              }
668          }
669      },
670
671      _weekdays: "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
672      weekdays : function (m) {
673          return this._weekdays[m.day()];
674      },
675
676      _weekdaysShort: "星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),
677      weekdaysShort : function (m) {
678          return this._weekdaysShort[m.day()];
679      },
680
681      _weekdaysMin: "周日_周一_周二_周三_周四_周五_周六".split("_"),
682      weekdaysMin : function (m) {
683          return this._weekdaysMin[m.day()];
684      },
685
686      weekdaysParse : function (weekdayName) {
687          var i, mom, regex;
688
689          if (!this._weekdaysParse) {
690              this._weekdaysParse = [];
691          }
692
693          for (i = 0; i < 7; i++) {
694              // make the regex if we don't have it already
695              if (!this._weekdaysParse[i]) {
696                  mom = moment([2000, 1]).day(i);
697                  regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
698                  this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
699              }
700              // test the regex
701              if (this._weekdaysParse[i].test(weekdayName)) {
702                  return i;
703              }
704          }
705      },
706
707      _longDateFormat : {
708          LT : "h:mm A",
709          L: "YYYY-MM-DD",
710          LL : "MMMM D YYYY",
711          LLL : "MMMM D YYYY LT",
712          LLLL : "dddd, MMMM D YYYY LT"
713      },
714      longDateFormat : function (key) {
715          var output = this._longDateFormat[key];
716          if (!output && this._longDateFormat[key.toUpperCase()]) {
717              output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
718                  return val.slice(1);
719              });
720              this._longDateFormat[key] = output;
721          }
722          return output;
723      },
724
725      isPM : function (input) {
726          // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
727          // Using charAt should be more compatible.
728          return ((input + '').toLowerCase().charAt(0) === 'p');
729      },
730
731      _meridiemParse : /[ap]\.?m?\.?/i,
732      meridiem : function (hours, minutes, isLower) {
733          if (hours > 11) {
734              return isLower ? 'pm' : 'PM';
735          } else {
736              return isLower ? 'am' : 'AM';
737          }
738      },
739
740      _calendar : {
741          sameDay : '[Today at] LT',
742          nextDay : '[Tomorrow at] LT',
743          nextWeek : 'dddd [at] LT',
744          lastDay : '[Yesterday at] LT',
745          lastWeek : '[Last] dddd [at] LT',
746          sameElse : 'L'
747      },
748      calendar : function (key, mom) {
749          var output = this._calendar[key];
750          return typeof output === 'function' ? output.apply(mom) : output;
751      },
752
753      _relativeTime : {
754          future : "in %s",
755          past : "%s ago",
756          s : "a few seconds",
757          m : "a minute",
758          mm : "%d minutes",
759          h : "an hour",
760          hh : "%d hours",
761          d : "a day",
762          dd : "%d days",
763          M : "a month",
764          MM : "%d months",
765          y : "a year",
766          yy : "%d years"
767      },
768      relativeTime : function (number, withoutSuffix, string, isFuture) {
769          var output = this._relativeTime[string];
770          return (typeof output === 'function') ?
771              output(number, withoutSuffix, string, isFuture) :
772              output.replace(/%d/i, number);
773      },
774      pastFuture : function (diff, output) {
775          var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
776          return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
777      },
778
779      ordinal : function (number) {
780          return this._ordinal.replace("%d", number);
781      },
782      _ordinal : "%d",
783
784      preparse : function (string) {
785          return string;
786      },
787
788      postformat : function (string) {
789          return string;
790      },
791
792      week : function (mom) {
793          return weekOfYear(mom, this._week.dow, this._week.doy).week;
794      },
795
796      _week : {
797          dow : 0, // Sunday is the first day of the week.
798          doy : 6  // The week that contains Jan 1st is the first week of the year.
799      },
800
801      _invalidDate: 'Invalid date',
802      invalidDate: function () {
803          return this._invalidDate;
804      }
805  });
806
807  // Loads a language definition into the `languages` cache.  The function
808  // takes a key and optionally values.  If not in the browser and no values
809  // are provided, it will load the language file module.  As a convenience,
810  // this function also returns the language values.
811  function loadLang(key, values) {
812      values.abbr = key;
813      if (!languages[key]) {
814          languages[key] = new Language();
815      }
816      languages[key].set(values);
817      return languages[key];
818  }
819
820  // Remove a language from the `languages` cache. Mostly useful in tests.
821  function unloadLang(key) {
822      delete languages[key];
823  }
824
825  // Determines which language definition to use and returns it.
826  //
827  // With no parameters, it will return the global language.  If you
828  // pass in a language key, such as 'en', it will return the
829  // definition for 'en', so long as 'en' has already been loaded using
830  // moment.lang.
831  function getLangDefinition(key) {
832      var i = 0, j, lang, next, split,
833          get = function (k) {
834              if (!languages[k] && hasModule) {
835                  try {
836                      require('./lang/' + k);
837                  } catch (e) { }
838              }
839              return languages[k];
840          };
841
842      if (!key) {
843          return moment.fn._lang;
844      }
845
846      if (!isArray(key)) {
847          //short-circuit everything else
848          lang = get(key);
849          if (lang) {
850              return lang;
851          }
852          key = [key];
853      }
854
855      //pick the language from the array
856      //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
857      //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
858      while (i < key.length) {
859          split = normalizeLanguage(key[i]).split('-');
860          j = split.length;
861          next = normalizeLanguage(key[i + 1]);
862          next = next ? next.split('-') : null;
863          while (j > 0) {
864              lang = get(split.slice(0, j).join('-'));
865              if (lang) {
866                  return lang;
867              }
868              if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
869                  //the next array item is better than a shallower substring of this one
870                  break;
871              }
872              j--;
873          }
874          i++;
875      }
876      return moment.fn._lang;
877  }
878
879  /************************************
880      Formatting
881  ************************************/
882
883
884  function removeFormattingTokens(input) {
885      if (input.match(/\[[\s\S]/)) {
886          return input.replace(/^\[|\]$/g, "");
887      }
888      return input.replace(/\\/g, "");
889  }
890
891  function makeFormatFunction(format) {
892      var array = format.match(formattingTokens), i, length;
893
894      for (i = 0, length = array.length; i < length; i++) {
895          if (formatTokenFunctions[array[i]]) {
896              array[i] = formatTokenFunctions[array[i]];
897          } else {
898              array[i] = removeFormattingTokens(array[i]);
899          }
900      }
901
902      return function (mom) {
903          var output = "";
904          for (i = 0; i < length; i++) {
905              output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
906          }
907          return output;
908      };
909  }
910
911  // format date using native date object
912  function formatMoment(m, format) {
913
914      if (!m.isValid()) {
915          return m.lang().invalidDate();
916      }
917
918      format = expandFormat(format, m.lang());
919
920      if (!formatFunctions[format]) {
921          formatFunctions[format] = makeFormatFunction(format);
922      }
923
924      return formatFunctions[format](m);
925  }
926
927  function expandFormat(format, lang) {
928      var i = 5;
929
930      function replaceLongDateFormatTokens(input) {
931          return lang.longDateFormat(input) || input;
932      }
933
934      localFormattingTokens.lastIndex = 0;
935      while (i >= 0 && localFormattingTokens.test(format)) {
936          format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
937          localFormattingTokens.lastIndex = 0;
938          i -= 1;
939      }
940
941      return format;
942  }
943
944
945  /************************************
946      Parsing
947  ************************************/
948
949
950  // get the regex to find the next token
951  function getParseRegexForToken(token, config) {
952      var a, strict = config._strict;
953      switch (token) {
954      case 'DDDD':
955          return parseTokenThreeDigits;
956      case 'YYYY':
957      case 'GGGG':
958      case 'gggg':
959          return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
960      case 'Y':
961      case 'G':
962      case 'g':
963          return parseTokenSignedNumber;
964      case 'YYYYYY':
965      case 'YYYYY':
966      case 'GGGGG':
967      case 'ggggg':
968          return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
969      case 'S':
970          if (strict) { return parseTokenOneDigit; }
971          /* falls through */
972      case 'SS':
973          if (strict) { return parseTokenTwoDigits; }
974          /* falls through */
975      case 'SSS':
976          if (strict) { return parseTokenThreeDigits; }
977          /* falls through */
978      case 'DDD':
979          return parseTokenOneToThreeDigits;
980      case 'MMM':
981      case 'MMMM':
982      case 'dd':
983      case 'ddd':
984      case 'dddd':
985          return parseTokenWord;
986      case 'a':
987      case 'A':
988          return getLangDefinition(config._l)._meridiemParse;
989      case 'X':
990          return parseTokenTimestampMs;
991      case 'Z':
992      case 'ZZ':
993          return parseTokenTimezone;
994      case 'T':
995          return parseTokenT;
996      case 'SSSS':
997          return parseTokenDigits;
998      case 'MM':
999      case 'DD':
1000      case 'YY':
1001      case 'GG':
1002      case 'gg':
1003      case 'HH':
1004      case 'hh':
1005      case 'mm':
1006      case 'ss':
1007      case 'ww':
1008      case 'WW':
1009          return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
1010      case 'M':
1011      case 'D':
1012      case 'd':
1013      case 'H':
1014      case 'h':
1015      case 'm':
1016      case 's':
1017      case 'w':
1018      case 'W':
1019      case 'e':
1020      case 'E':
1021          return parseTokenOneOrTwoDigits;
1022      default :
1023          a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
1024          return a;
1025      }
1026  }
1027
1028  function timezoneMinutesFromString(string) {
1029      string = string || "";
1030      var possibleTzMatches = (string.match(parseTokenTimezone) || []),
1031          tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
1032          parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
1033          minutes = +(parts[1] * 60) + toInt(parts[2]);
1034
1035      return parts[0] === '+' ? -minutes : minutes;
1036  }
1037
1038  // function to convert string input to date
1039  function addTimeToArrayFromToken(token, input, config) {
1040      var a, datePartArray = config._a;
1041
1042      switch (token) {
1043      // MONTH
1044      case 'M' : // fall through to MM
1045      case 'MM' :
1046          if (input != null) {
1047              datePartArray[MONTH] = toInt(input) - 1;
1048          }
1049          break;
1050      case 'MMM' : // fall through to MMMM
1051      case 'MMMM' :
1052          a = getLangDefinition(config._l).monthsParse(input);
1053          // if we didn't find a month name, mark the date as invalid.
1054          if (a != null) {
1055              datePartArray[MONTH] = a;
1056          } else {
1057              config._pf.invalidMonth = input;
1058          }
1059          break;
1060      // DAY OF MONTH
1061      case 'D' : // fall through to DD
1062      case 'DD' :
1063          if (input != null) {
1064              datePartArray[DATE] = toInt(input);
1065          }
1066          break;
1067      // DAY OF YEAR
1068      case 'DDD' : // fall through to DDDD
1069      case 'DDDD' :
1070          if (input != null) {
1071              config._dayOfYear = toInt(input);
1072          }
1073
1074          break;
1075      // YEAR
1076      case 'YY' :
1077          datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
1078          break;
1079      case 'YYYY' :
1080      case 'YYYYY' :
1081      case 'YYYYYY' :
1082          datePartArray[YEAR] = toInt(input);
1083          break;
1084      // AM / PM
1085      case 'a' : // fall through to A
1086      case 'A' :
1087          config._isPm = getLangDefinition(config._l).isPM(input);
1088          break;
1089      // 24 HOUR
1090      case 'H' : // fall through to hh
1091      case 'HH' : // fall through to hh
1092      case 'h' : // fall through to hh
1093      case 'hh' :
1094          datePartArray[HOUR] = toInt(input);
1095          break;
1096      // MINUTE
1097      case 'm' : // fall through to mm
1098      case 'mm' :
1099          datePartArray[MINUTE] = toInt(input);
1100          break;
1101      // SECOND
1102      case 's' : // fall through to ss
1103      case 'ss' :
1104          datePartArray[SECOND] = toInt(input);
1105          break;
1106      // MILLISECOND
1107      case 'S' :
1108      case 'SS' :
1109      case 'SSS' :
1110      case 'SSSS' :
1111          datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
1112          break;
1113      // UNIX TIMESTAMP WITH MS
1114      case 'X':
1115          config._d = new Date(parseFloat(input) * 1000);
1116          break;
1117      // TIMEZONE
1118      case 'Z' : // fall through to ZZ
1119      case 'ZZ' :
1120          config._useUTC = true;
1121          config._tzm = timezoneMinutesFromString(input);
1122          break;
1123      case 'w':
1124      case 'ww':
1125      case 'W':
1126      case 'WW':
1127      case 'd':
1128      case 'dd':
1129      case 'ddd':
1130      case 'dddd':
1131      case 'e':
1132      case 'E':
1133          token = token.substr(0, 1);
1134          /* falls through */
1135      case 'gg':
1136      case 'gggg':
1137      case 'GG':
1138      case 'GGGG':
1139      case 'GGGGG':
1140          token = token.substr(0, 2);
1141          if (input) {
1142              config._w = config._w || {};
1143              config._w[token] = input;
1144          }
1145          break;
1146      }
1147  }
1148
1149  // convert an array to a date.
1150  // the array should mirror the parameters below
1151  // note: all values past the year are optional and will default to the lowest possible value.
1152  // [year, month, day , hour, minute, second, millisecond]
1153  function dateFromConfig(config) {
1154      var i, date, input = [], currentDate,
1155          yearToUse, fixYear, w, temp, lang, weekday, week;
1156
1157      if (config._d) {
1158          return;
1159      }
1160
1161      currentDate = currentDateArray(config);
1162
1163      //compute day of the year from weeks and weekdays
1164      if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1165          fixYear = function (val) {
1166              var int_val = parseInt(val, 10);
1167              return val ?
1168                (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) :
1169                (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
1170          };
1171
1172          w = config._w;
1173          if (w.GG != null || w.W != null || w.E != null) {
1174              temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
1175          }
1176          else {
1177              lang = getLangDefinition(config._l);
1178              weekday = w.d != null ?  parseWeekday(w.d, lang) :
1179                (w.e != null ?  parseInt(w.e, 10) + lang._week.dow : 0);
1180
1181              week = parseInt(w.w, 10) || 1;
1182
1183              //if we're parsing 'd', then the low day numbers may be next week
1184              if (w.d != null && weekday < lang._week.dow) {
1185                  week++;
1186              }
1187
1188              temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
1189          }
1190
1191          config._a[YEAR] = temp.year;
1192          config._dayOfYear = temp.dayOfYear;
1193      }
1194
1195      //if the day of the year is set, figure out what it is
1196      if (config._dayOfYear) {
1197          yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
1198
1199          if (config._dayOfYear > daysInYear(yearToUse)) {
1200              config._pf._overflowDayOfYear = true;
1201          }
1202
1203          date = makeUTCDate(yearToUse, 0, config._dayOfYear);
1204          config._a[MONTH] = date.getUTCMonth();
1205          config._a[DATE] = date.getUTCDate();
1206      }
1207
1208      // Default to current date.
1209      // * if no year, month, day of month are given, default to today
1210      // * if day of month is given, default month and year
1211      // * if month is given, default only year
1212      // * if year is given, don't default anything
1213      for (i = 0; i < 3 && config._a[i] == null; ++i) {
1214          config._a[i] = input[i] = currentDate[i];
1215      }
1216
1217      // Zero out whatever was not defaulted, including time
1218      for (; i < 7; i++) {
1219          config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1220      }
1221
1222      // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
1223      input[HOUR] += toInt((config._tzm || 0) / 60);
1224      input[MINUTE] += toInt((config._tzm || 0) % 60);
1225
1226      config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
1227  }
1228
1229  function dateFromObject(config) {
1230      var normalizedInput;
1231
1232      if (config._d) {
1233          return;
1234      }
1235
1236      normalizedInput = normalizeObjectUnits(config._i);
1237      config._a = [
1238          normalizedInput.year,
1239          normalizedInput.month,
1240          normalizedInput.day,
1241          normalizedInput.hour,
1242          normalizedInput.minute,
1243          normalizedInput.second,
1244          normalizedInput.millisecond
1245      ];
1246
1247      dateFromConfig(config);
1248  }
1249
1250  function currentDateArray(config) {
1251      var now = new Date();
1252      if (config._useUTC) {
1253          return [
1254              now.getUTCFullYear(),
1255              now.getUTCMonth(),
1256              now.getUTCDate()
1257          ];
1258      } else {
1259          return [now.getFullYear(), now.getMonth(), now.getDate()];
1260      }
1261  }
1262
1263  // date from string and format string
1264  function makeDateFromStringAndFormat(config) {
1265
1266      config._a = [];
1267      config._pf.empty = true;
1268
1269      // This array is used to make a Date, either with `new Date` or `Date.UTC`
1270      var lang = getLangDefinition(config._l),
1271          string = '' + config._i,
1272          i, parsedInput, tokens, token, skipped,
1273          stringLength = string.length,
1274          totalParsedInputLength = 0;
1275
1276      tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
1277
1278      for (i = 0; i < tokens.length; i++) {
1279          token = tokens[i];
1280          parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
1281          if (parsedInput) {
1282              skipped = string.substr(0, string.indexOf(parsedInput));
1283              if (skipped.length > 0) {
1284                  config._pf.unusedInput.push(skipped);
1285              }
1286              string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1287              totalParsedInputLength += parsedInput.length;
1288          }
1289          // don't parse if it's not a known token
1290          if (formatTokenFunctions[token]) {
1291              if (parsedInput) {
1292                  config._pf.empty = false;
1293              }
1294              else {
1295                  config._pf.unusedTokens.push(token);
1296              }
1297              addTimeToArrayFromToken(token, parsedInput, config);
1298          }
1299          else if (config._strict && !parsedInput) {
1300              config._pf.unusedTokens.push(token);
1301          }
1302      }
1303
1304      // add remaining unparsed input length to the string
1305      config._pf.charsLeftOver = stringLength - totalParsedInputLength;
1306      if (string.length > 0) {
1307          config._pf.unusedInput.push(string);
1308      }
1309
1310      // handle am pm
1311      if (config._isPm && config._a[HOUR] < 12) {
1312          config._a[HOUR] += 12;
1313      }
1314      // if is 12 am, change hours to 0
1315      if (config._isPm === false && config._a[HOUR] === 12) {
1316          config._a[HOUR] = 0;
1317      }
1318
1319      dateFromConfig(config);
1320      checkOverflow(config);
1321  }
1322
1323  function unescapeFormat(s) {
1324      return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
1325          return p1 || p2 || p3 || p4;
1326      });
1327  }
1328
1329  // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1330  function regexpEscape(s) {
1331      return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1332  }
1333
1334  // date from string and array of format strings
1335  function makeDateFromStringAndArray(config) {
1336      var tempConfig,
1337          bestMoment,
1338
1339          scoreToBeat,
1340          i,
1341          currentScore;
1342
1343      if (config._f.length === 0) {
1344          config._pf.invalidFormat = true;
1345          config._d = new Date(NaN);
1346          return;
1347      }
1348
1349      for (i = 0; i < config._f.length; i++) {
1350          currentScore = 0;
1351          tempConfig = extend({}, config);
1352          tempConfig._pf = defaultParsingFlags();
1353          tempConfig._f = config._f[i];
1354          makeDateFromStringAndFormat(tempConfig);
1355
1356          if (!isValid(tempConfig)) {
1357              continue;
1358          }
1359
1360          // if there is any input that was not parsed add a penalty for that format
1361          currentScore += tempConfig._pf.charsLeftOver;
1362
1363          //or tokens
1364          currentScore += tempConfig._pf.unusedTokens.length * 10;
1365
1366          tempConfig._pf.score = currentScore;
1367
1368          if (scoreToBeat == null || currentScore < scoreToBeat) {
1369              scoreToBeat = currentScore;
1370              bestMoment = tempConfig;
1371          }
1372      }
1373
1374      extend(config, bestMoment || tempConfig);
1375  }
1376
1377  // date from iso format
1378  function makeDateFromString(config) {
1379      var i, l,
1380          string = config._i,
1381          match = isoRegex.exec(string);
1382
1383      if (match) {
1384          config._pf.iso = true;
1385          for (i = 0, l = isoDates.length; i < l; i++) {
1386              if (isoDates[i][1].exec(string)) {
1387                  // match[5] should be "T" or undefined
1388                  config._f = isoDates[i][0] + (match[6] || " ");
1389                  break;
1390              }
1391          }
1392          for (i = 0, l = isoTimes.length; i < l; i++) {
1393              if (isoTimes[i][1].exec(string)) {
1394                  config._f += isoTimes[i][0];
1395                  break;
1396              }
1397          }
1398          if (string.match(parseTokenTimezone)) {
1399              config._f += "Z";
1400          }
1401          makeDateFromStringAndFormat(config);
1402      }
1403      else {
1404          config._d = new Date(string);
1405      }
1406  }
1407
1408  function makeDateFromInput(config) {
1409      var input = config._i,
1410          matched = aspNetJsonRegex.exec(input);
1411
1412      if (input === undefined) {
1413          config._d = new Date();
1414      } else if (matched) {
1415          config._d = new Date(+matched[1]);
1416      } else if (typeof input === 'string') {
1417          makeDateFromString(config);
1418      } else if (isArray(input)) {
1419          config._a = input.slice(0);
1420          dateFromConfig(config);
1421      } else if (isDate(input)) {
1422          config._d = new Date(+input);
1423      } else if (typeof(input) === 'object') {
1424          dateFromObject(config);
1425      } else {
1426          config._d = new Date(input);
1427      }
1428  }
1429
1430  function makeDate(y, m, d, h, M, s, ms) {
1431      //can't just apply() to create a date:
1432      //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1433      var date = new Date(y, m, d, h, M, s, ms);
1434
1435      //the date constructor doesn't accept years < 1970
1436      if (y < 1970) {
1437          date.setFullYear(y);
1438      }
1439      return date;
1440  }
1441
1442  function makeUTCDate(y) {
1443      var date = new Date(Date.UTC.apply(null, arguments));
1444      if (y < 1970) {
1445          date.setUTCFullYear(y);
1446      }
1447      return date;
1448  }
1449
1450  function parseWeekday(input, language) {
1451      if (typeof input === 'string') {
1452          if (!isNaN(input)) {
1453              input = parseInt(input, 10);
1454          }
1455          else {
1456              input = language.weekdaysParse(input);
1457              if (typeof input !== 'number') {
1458                  return null;
1459              }
1460          }
1461      }
1462      return input;
1463  }
1464
1465  /************************************
1466      Relative Time
1467  ************************************/
1468
1469
1470  // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
1471  function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
1472      return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
1473  }
1474
1475  function relativeTime(milliseconds, withoutSuffix, lang) {
1476      var seconds = round(Math.abs(milliseconds) / 1000),
1477          minutes = round(seconds / 60),
1478          hours = round(minutes / 60),
1479          days = round(hours / 24),
1480          years = round(days / 365),
1481          args = seconds < 45 && ['s', seconds] ||
1482              minutes === 1 && ['m'] ||
1483              minutes < 45 && ['mm', minutes] ||
1484              hours === 1 && ['h'] ||
1485              hours < 22 && ['hh', hours] ||
1486              days === 1 && ['d'] ||
1487              days <= 25 && ['dd', days] ||
1488              days <= 45 && ['M'] ||
1489              days < 345 && ['MM', round(days / 30)] ||
1490              years === 1 && ['y'] || ['yy', years];
1491      args[2] = withoutSuffix;
1492      args[3] = milliseconds > 0;
1493      args[4] = lang;
1494      return substituteTimeAgo.apply({}, args);
1495  }
1496
1497
1498  /************************************
1499      Week of Year
1500  ************************************/
1501
1502
1503  // firstDayOfWeek       0 = sun, 6 = sat
1504  //                      the day of the week that starts the week
1505  //                      (usually sunday or monday)
1506  // firstDayOfWeekOfYear 0 = sun, 6 = sat
1507  //                      the first week is the week that contains the first
1508  //                      of this day of the week
1509  //                      (eg. ISO weeks use thursday (4))
1510  function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
1511      var end = firstDayOfWeekOfYear - firstDayOfWeek,
1512          daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
1513          adjustedMoment;
1514
1515
1516      if (daysToDayOfWeek > end) {
1517          daysToDayOfWeek -= 7;
1518      }
1519
1520      if (daysToDayOfWeek < end - 7) {
1521          daysToDayOfWeek += 7;
1522      }
1523
1524      adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
1525      return {
1526          week: Math.ceil(adjustedMoment.dayOfYear() / 7),
1527          year: adjustedMoment.year()
1528      };
1529  }
1530
1531  //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1532  function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1533      var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
1534
1535      weekday = weekday != null ? weekday : firstDayOfWeek;
1536      daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
1537      dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
1538
1539      return {
1540          year: dayOfYear > 0 ? year : year - 1,
1541          dayOfYear: dayOfYear > 0 ?  dayOfYear : daysInYear(year - 1) + dayOfYear
1542      };
1543  }
1544
1545  /************************************
1546      Top Level Functions
1547  ************************************/
1548
1549  function makeMoment(config) {
1550      var input = config._i,
1551          format = config._f;
1552
1553      if (input === null) {
1554          return moment.invalid({nullInput: true});
1555      }
1556
1557      if (typeof input === 'string') {
1558          config._i = input = getLangDefinition().preparse(input);
1559      }
1560
1561      if (moment.isMoment(input)) {
1562          config = cloneMoment(input);
1563
1564          config._d = new Date(+input._d);
1565      } else if (format) {
1566          if (isArray(format)) {
1567              makeDateFromStringAndArray(config);
1568          } else {
1569              makeDateFromStringAndFormat(config);
1570          }
1571      } else {
1572          makeDateFromInput(config);
1573      }
1574
1575      return new Moment(config);
1576  }
1577
1578  moment = function (input, format, lang, strict) {
1579      var c;
1580
1581      if (typeof(lang) === "boolean") {
1582          strict = lang;
1583          lang = undefined;
1584      }
1585      // object construction must be done this way.
1586      // https://github.com/moment/moment/issues/1423
1587      c = {};
1588      c._isAMomentObject = true;
1589      c._i = input;
1590      c._f = format;
1591      c._l = lang;
1592      c._strict = strict;
1593      c._isUTC = false;
1594      c._pf = defaultParsingFlags();
1595
1596      return makeMoment(c);
1597  };
1598
1599  // creating with utc
1600  moment.utc = function (input, format, lang, strict) {
1601      var c;
1602
1603      if (typeof(lang) === "boolean") {
1604          strict = lang;
1605          lang = undefined;
1606      }
1607      // object construction must be done this way.
1608      // https://github.com/moment/moment/issues/1423
1609      c = {};
1610      c._isAMomentObject = true;
1611      c._useUTC = true;
1612      c._isUTC = true;
1613      c._l = lang;
1614      c._i = input;
1615      c._f = format;
1616      c._strict = strict;
1617      c._pf = defaultParsingFlags();
1618
1619      return makeMoment(c).utc();
1620  };
1621
1622  // creating with unix timestamp (in seconds)
1623  moment.unix = function (input) {
1624      return moment(input * 1000);
1625  };
1626
1627  // duration
1628  moment.duration = function (input, key) {
1629      var duration = input,
1630          // matching against regexp is expensive, do it on demand
1631          match = null,
1632          sign,
1633          ret,
1634          parseIso;
1635
1636      if (moment.isDuration(input)) {
1637          duration = {
1638              ms: input._milliseconds,
1639              d: input._days,
1640              M: input._months
1641          };
1642      } else if (typeof input === 'number') {
1643          duration = {};
1644          if (key) {
1645              duration[key] = input;
1646          } else {
1647              duration.milliseconds = input;
1648          }
1649      } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
1650          sign = (match[1] === "-") ? -1 : 1;
1651          duration = {
1652              y: 0,
1653              d: toInt(match[DATE]) * sign,
1654              h: toInt(match[HOUR]) * sign,
1655              m: toInt(match[MINUTE]) * sign,
1656              s: toInt(match[SECOND]) * sign,
1657              ms: toInt(match[MILLISECOND]) * sign
1658          };
1659      } else if (!!(match = isoDurationRegex.exec(input))) {
1660          sign = (match[1] === "-") ? -1 : 1;
1661          parseIso = function (inp) {
1662              // We'd normally use ~~inp for this, but unfortunately it also
1663              // converts floats to ints.
1664              // inp may be undefined, so careful calling replace on it.
1665              var res = inp && parseFloat(inp.replace(',', '.'));
1666              // apply sign while we're at it
1667              return (isNaN(res) ? 0 : res) * sign;
1668          };
1669          duration = {
1670              y: parseIso(match[2]),
1671              M: parseIso(match[3]),
1672              d: parseIso(match[4]),
1673              h: parseIso(match[5]),
1674              m: parseIso(match[6]),
1675              s: parseIso(match[7]),
1676              w: parseIso(match[8])
1677          };
1678      }
1679
1680      ret = new Duration(duration);
1681
1682      if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
1683          ret._lang = input._lang;
1684      }
1685
1686      return ret;
1687  };
1688
1689  // version number
1690  moment.version = VERSION;
1691
1692  // default format
1693  moment.defaultFormat = isoFormat;
1694
1695  // This function will be called whenever a moment is mutated.
1696  // It is intended to keep the offset in sync with the timezone.
1697  moment.updateOffset = function () {};
1698
1699  // This function will load languages and then set the global language.  If
1700  // no arguments are passed in, it will simply return the current global
1701  // language key.
1702  moment.lang = function (key, values) {
1703      var r;
1704      if (!key) {
1705          return moment.fn._lang._abbr;
1706      }
1707      if (values) {
1708          loadLang(normalizeLanguage(key), values);
1709      } else if (values === null) {
1710          unloadLang(key);
1711          key = 'en';
1712      } else if (!languages[key]) {
1713          getLangDefinition(key);
1714      }
1715      r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
1716      return r._abbr;
1717  };
1718
1719  // returns language data
1720  moment.langData = function (key) {
1721      if (key && key._lang && key._lang._abbr) {
1722          key = key._lang._abbr;
1723      }
1724      return getLangDefinition(key);
1725  };
1726
1727  // compare moment object
1728  moment.isMoment = function (obj) {
1729      return obj instanceof Moment ||
1730          (obj != null &&  obj.hasOwnProperty('_isAMomentObject'));
1731  };
1732
1733  // for typechecking Duration objects
1734  moment.isDuration = function (obj) {
1735      return obj instanceof Duration;
1736  };
1737
1738  for (i = lists.length - 1; i >= 0; --i) {
1739      makeList(lists[i]);
1740  }
1741
1742  moment.normalizeUnits = function (units) {
1743      return normalizeUnits(units);
1744  };
1745
1746  moment.invalid = function (flags) {
1747      var m = moment.utc(NaN);
1748      if (flags != null) {
1749          extend(m._pf, flags);
1750      }
1751      else {
1752          m._pf.userInvalidated = true;
1753      }
1754
1755      return m;
1756  };
1757
1758  moment.parseZone = function (input) {
1759      return moment(input).parseZone();
1760  };
1761
1762  /************************************
1763      Moment Prototype
1764  ************************************/
1765
1766
1767  extend(moment.fn = Moment.prototype, {
1768
1769      clone : function () {
1770          return moment(this);
1771      },
1772
1773      valueOf : function () {
1774          return +this._d + ((this._offset || 0) * 60000);
1775      },
1776
1777      unix : function () {
1778          return Math.floor(+this / 1000);
1779      },
1780
1781      toString : function () {
1782          return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
1783      },
1784
1785      toDate : function () {
1786          return this._offset ? new Date(+this) : this._d;
1787      },
1788
1789      toISOString : function () {
1790          var m = moment(this).utc();
1791          if (0 < m.year() && m.year() <= 9999) {
1792              return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1793          } else {
1794              return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1795          }
1796      },
1797
1798      toArray : function () {
1799          var m = this;
1800          return [
1801              m.year(),
1802              m.month(),
1803              m.date(),
1804              m.hours(),
1805              m.minutes(),
1806              m.seconds(),
1807              m.milliseconds()
1808          ];
1809      },
1810
1811      isValid : function () {
1812          return isValid(this);
1813      },
1814
1815      isDSTShifted : function () {
1816
1817          if (this._a) {
1818              return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
1819          }
1820
1821          return false;
1822      },
1823
1824      parsingFlags : function () {
1825          return extend({}, this._pf);
1826      },
1827
1828      invalidAt: function () {
1829          return this._pf.overflow;
1830      },
1831
1832      utc : function () {
1833          return this.zone(0);
1834      },
1835
1836      local : function () {
1837          this.zone(0);
1838          this._isUTC = false;
1839          return this;
1840      },
1841
1842      format : function (inputString) {
1843          var output = formatMoment(this, inputString || moment.defaultFormat);
1844          return this.lang().postformat(output);
1845      },
1846
1847      add : function (input, val) {
1848          var dur;
1849          // switch args to support add('s', 1) and add(1, 's')
1850          if (typeof input === 'string') {
1851              dur = moment.duration(+val, input);
1852          } else {
1853              dur = moment.duration(input, val);
1854          }
1855          addOrSubtractDurationFromMoment(this, dur, 1);
1856          return this;
1857      },
1858
1859      subtract : function (input, val) {
1860          var dur;
1861          // switch args to support subtract('s', 1) and subtract(1, 's')
1862          if (typeof input === 'string') {
1863              dur = moment.duration(+val, input);
1864          } else {
1865              dur = moment.duration(input, val);
1866          }
1867          addOrSubtractDurationFromMoment(this, dur, -1);
1868          return this;
1869      },
1870
1871      diff : function (input, units, asFloat) {
1872          var that = makeAs(input, this),
1873              zoneDiff = (this.zone() - that.zone()) * 6e4,
1874              diff, output;
1875
1876          units = normalizeUnits(units);
1877
1878          if (units === 'year' || units === 'month') {
1879              // average number of days in the months in the given dates
1880              diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
1881              // difference in months
1882              output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
1883              // adjust by taking difference in days, average number of days
1884              // and dst in the given months.
1885              output += ((this - moment(this).startOf('month')) -
1886                      (that - moment(that).startOf('month'))) / diff;
1887              // same as above but with zones, to negate all dst
1888              output -= ((this.zone() - moment(this).startOf('month').zone()) -
1889                      (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
1890              if (units === 'year') {
1891                  output = output / 12;
1892              }
1893          } else {
1894              diff = (this - that);
1895              output = units === 'second' ? diff / 1e3 : // 1000
1896                  units === 'minute' ? diff / 6e4 : // 1000 * 60
1897                  units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
1898                  units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
1899                  units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
1900                  diff;
1901          }
1902          return asFloat ? output : absRound(output);
1903      },
1904
1905      from : function (time, withoutSuffix) {
1906          return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
1907      },
1908
1909      fromNow : function (withoutSuffix) {
1910          return this.from(moment(), withoutSuffix);
1911      },
1912
1913      calendar : function () {
1914          // We want to compare the start of today, vs this.
1915          // Getting start-of-today depends on whether we're zone'd or not.
1916          var sod = makeAs(moment(), this).startOf('day'),
1917              diff = this.diff(sod, 'days', true),
1918              format = diff < -6 ? 'sameElse' :
1919                  diff < -1 ? 'lastWeek' :
1920                  diff < 0 ? 'lastDay' :
1921                  diff < 1 ? 'sameDay' :
1922                  diff < 2 ? 'nextDay' :
1923                  diff < 7 ? 'nextWeek' : 'sameElse';
1924          return this.format(this.lang().calendar(format, this));
1925      },
1926
1927      isLeapYear : function () {
1928          return isLeapYear(this.year());
1929      },
1930
1931      isDST : function () {
1932          return (this.zone() < this.clone().month(0).zone() ||
1933              this.zone() < this.clone().month(5).zone());
1934      },
1935
1936      day : function (input) {
1937          var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1938          if (input != null) {
1939              input = parseWeekday(input, this.lang());
1940              return this.add({ d : input - day });
1941          } else {
1942              return day;
1943          }
1944      },
1945
1946      month : function (input) {
1947          var utc = this._isUTC ? 'UTC' : '',
1948              dayOfMonth;
1949
1950          if (input != null) {
1951              if (typeof input === 'string') {
1952                  input = this.lang().monthsParse(input);
1953                  if (typeof input !== 'number') {
1954                      return this;
1955                  }
1956              }
1957
1958              dayOfMonth = this.date();
1959              this.date(1);
1960              this._d['set' + utc + 'Month'](input);
1961              this.date(Math.min(dayOfMonth, this.daysInMonth()));
1962
1963              moment.updateOffset(this);
1964              return this;
1965          } else {
1966              return this._d['get' + utc + 'Month']();
1967          }
1968      },
1969
1970      startOf: function (units) {
1971          units = normalizeUnits(units);
1972          // the following switch intentionally omits break keywords
1973          // to utilize falling through the cases.
1974          switch (units) {
1975          case 'year':
1976              this.month(0);
1977              /* falls through */
1978          case 'month':
1979              this.date(1);
1980              /* falls through */
1981          case 'week':
1982          case 'isoWeek':
1983          case 'day':
1984              this.hours(0);
1985              /* falls through */
1986          case 'hour':
1987              this.minutes(0);
1988              /* falls through */
1989          case 'minute':
1990              this.seconds(0);
1991              /* falls through */
1992          case 'second':
1993              this.milliseconds(0);
1994              /* falls through */
1995          }
1996
1997          // weeks are a special case
1998          if (units === 'week') {
1999              this.weekday(0);
2000          } else if (units === 'isoWeek') {
2001              this.isoWeekday(1);
2002          }
2003
2004          return this;
2005      },
2006
2007      endOf: function (units) {
2008          units = normalizeUnits(units);
2009          return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
2010      },
2011
2012      isAfter: function (input, units) {
2013          units = typeof units !== 'undefined' ? units : 'millisecond';
2014          return +this.clone().startOf(units) > +moment(input).startOf(units);
2015      },
2016
2017      isBefore: function (input, units) {
2018          units = typeof units !== 'undefined' ? units : 'millisecond';
2019          return +this.clone().startOf(units) < +moment(input).startOf(units);
2020      },
2021
2022      isSame: function (input, units) {
2023          units = units || 'ms';
2024          return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
2025      },
2026
2027      min: function (other) {
2028          other = moment.apply(null, arguments);
2029          return other < this ? this : other;
2030      },
2031
2032      max: function (other) {
2033          other = moment.apply(null, arguments);
2034          return other > this ? this : other;
2035      },
2036
2037      zone : function (input) {
2038          var offset = this._offset || 0;
2039          if (input != null) {
2040              if (typeof input === "string") {
2041                  input = timezoneMinutesFromString(input);
2042              }
2043              if (Math.abs(input) < 16) {
2044                  input = input * 60;
2045              }
2046              this._offset = input;
2047              this._isUTC = true;
2048              if (offset !== input) {
2049                  addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
2050              }
2051          } else {
2052              return this._isUTC ? offset : this._d.getTimezoneOffset();
2053          }
2054          return this;
2055      },
2056
2057      zoneAbbr : function () {
2058          return this._isUTC ? "UTC" : "";
2059      },
2060
2061      zoneName : function () {
2062          return this._isUTC ? "Coordinated Universal Time" : "";
2063      },
2064
2065      parseZone : function () {
2066          if (this._tzm) {
2067              this.zone(this._tzm);
2068          } else if (typeof this._i === 'string') {
2069              this.zone(this._i);
2070          }
2071          return this;
2072      },
2073
2074      hasAlignedHourOffset : function (input) {
2075          if (!input) {
2076              input = 0;
2077          }
2078          else {
2079              input = moment(input).zone();
2080          }
2081
2082          return (this.zone() - input) % 60 === 0;
2083      },
2084
2085      daysInMonth : function () {
2086          return daysInMonth(this.year(), this.month());
2087      },
2088
2089      dayOfYear : function (input) {
2090          var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
2091          return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
2092      },
2093
2094      quarter : function () {
2095          return Math.ceil((this.month() + 1.0) / 3.0);
2096      },
2097
2098      weekYear : function (input) {
2099          var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
2100          return input == null ? year : this.add("y", (input - year));
2101      },
2102
2103      isoWeekYear : function (input) {
2104          var year = weekOfYear(this, 1, 4).year;
2105          return input == null ? year : this.add("y", (input - year));
2106      },
2107
2108      week : function (input) {
2109          var week = this.lang().week(this);
2110          return input == null ? week : this.add("d", (input - week) * 7);
2111      },
2112
2113      isoWeek : function (input) {
2114          var week = weekOfYear(this, 1, 4).week;
2115          return input == null ? week : this.add("d", (input - week) * 7);
2116      },
2117
2118      weekday : function (input) {
2119          var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
2120          return input == null ? weekday : this.add("d", input - weekday);
2121      },
2122
2123      isoWeekday : function (input) {
2124          // behaves the same as moment#day except
2125          // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
2126          // as a setter, sunday should belong to the previous week.
2127          return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
2128      },
2129
2130      get : function (units) {
2131          units = normalizeUnits(units);
2132          return this[units]();
2133      },
2134
2135      set : function (units, value) {
2136          units = normalizeUnits(units);
2137          if (typeof this[units] === 'function') {
2138              this[units](value);
2139          }
2140          return this;
2141      },
2142
2143      // If passed a language key, it will set the language for this
2144      // instance.  Otherwise, it will return the language configuration
2145      // variables for this instance.
2146      lang : function (key) {
2147          if (key === undefined) {
2148              return this._lang;
2149          } else {
2150              this._lang = getLangDefinition(key);
2151              return this;
2152          }
2153      }
2154  });
2155
2156  // helper for adding shortcuts
2157  function makeGetterAndSetter(name, key) {
2158      moment.fn[name] = moment.fn[name + 's'] = function (input) {
2159          var utc = this._isUTC ? 'UTC' : '';
2160          if (input != null) {
2161              this._d['set' + utc + key](input);
2162              moment.updateOffset(this);
2163              return this;
2164          } else {
2165              return this._d['get' + utc + key]();
2166          }
2167      };
2168  }
2169
2170  // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
2171  for (i = 0; i < proxyGettersAndSetters.length; i ++) {
2172      makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
2173  }
2174
2175  // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
2176  makeGetterAndSetter('year', 'FullYear');
2177
2178  // add plural methods
2179  moment.fn.days = moment.fn.day;
2180  moment.fn.months = moment.fn.month;
2181  moment.fn.weeks = moment.fn.week;
2182  moment.fn.isoWeeks = moment.fn.isoWeek;
2183
2184  // add aliased format methods
2185  moment.fn.toJSON = moment.fn.toISOString;
2186
2187  /************************************
2188      Duration Prototype
2189  ************************************/
2190
2191
2192  extend(moment.duration.fn = Duration.prototype, {
2193
2194      _bubble : function () {
2195          var milliseconds = this._milliseconds,
2196              days = this._days,
2197              months = this._months,
2198              data = this._data,
2199              seconds, minutes, hours, years;
2200
2201          // The following code bubbles up values, see the tests for
2202          // examples of what that means.
2203          data.milliseconds = milliseconds % 1000;
2204
2205          seconds = absRound(milliseconds / 1000);
2206          data.seconds = seconds % 60;
2207
2208          minutes = absRound(seconds / 60);
2209          data.minutes = minutes % 60;
2210
2211          hours = absRound(minutes / 60);
2212          data.hours = hours % 24;
2213
2214          days += absRound(hours / 24);
2215          data.days = days % 30;
2216
2217          months += absRound(days / 30);
2218          data.months = months % 12;
2219
2220          years = absRound(months / 12);
2221          data.years = years;
2222      },
2223
2224      weeks : function () {
2225          return absRound(this.days() / 7);
2226      },
2227
2228      valueOf : function () {
2229          return this._milliseconds +
2230            this._days * 864e5 +
2231            (this._months % 12) * 2592e6 +
2232            toInt(this._months / 12) * 31536e6;
2233      },
2234
2235      humanize : function (withSuffix) {
2236          var difference = +this,
2237              output = relativeTime(difference, !withSuffix, this.lang());
2238
2239          if (withSuffix) {
2240              output = this.lang().pastFuture(difference, output);
2241          }
2242
2243          return this.lang().postformat(output);
2244      },
2245
2246      add : function (input, val) {
2247          // supports only 2.0-style add(1, 's') or add(moment)
2248          var dur = moment.duration(input, val);
2249
2250          this._milliseconds += dur._milliseconds;
2251          this._days += dur._days;
2252          this._months += dur._months;
2253
2254          this._bubble();
2255
2256          return this;
2257      },
2258
2259      subtract : function (input, val) {
2260          var dur = moment.duration(input, val);
2261
2262          this._milliseconds -= dur._milliseconds;
2263          this._days -= dur._days;
2264          this._months -= dur._months;
2265
2266          this._bubble();
2267
2268          return this;
2269      },
2270
2271      get : function (units) {
2272          units = normalizeUnits(units);
2273          return this[units.toLowerCase() + 's']();
2274      },
2275
2276      as : function (units) {
2277          units = normalizeUnits(units);
2278          return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
2279      },
2280
2281      lang : moment.fn.lang,
2282
2283      toIsoString : function () {
2284          // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
2285          var years = Math.abs(this.years()),
2286              months = Math.abs(this.months()),
2287              days = Math.abs(this.days()),
2288              hours = Math.abs(this.hours()),
2289              minutes = Math.abs(this.minutes()),
2290              seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
2291
2292          if (!this.asSeconds()) {
2293              // this is the same as C#'s (Noda) and python (isodate)...
2294              // but not other JS (goog.date)
2295              return 'P0D';
2296          }
2297
2298          return (this.asSeconds() < 0 ? '-' : '') +
2299              'P' +
2300              (years ? years + 'Y' : '') +
2301              (months ? months + 'M' : '') +
2302              (days ? days + 'D' : '') +
2303              ((hours || minutes || seconds) ? 'T' : '') +
2304              (hours ? hours + 'H' : '') +
2305              (minutes ? minutes + 'M' : '') +
2306              (seconds ? seconds + 'S' : '');
2307      }
2308  });
2309
2310  function makeDurationGetter(name) {
2311      moment.duration.fn[name] = function () {
2312          return this._data[name];
2313      };
2314  }
2315
2316  function makeDurationAsGetter(name, factor) {
2317      moment.duration.fn['as' + name] = function () {
2318          return +this / factor;
2319      };
2320  }
2321
2322  for (i in unitMillisecondFactors) {
2323      if (unitMillisecondFactors.hasOwnProperty(i)) {
2324          makeDurationAsGetter(i, unitMillisecondFactors[i]);
2325          makeDurationGetter(i.toLowerCase());
2326      }
2327  }
2328
2329  makeDurationAsGetter('Weeks', 6048e5);
2330  moment.duration.fn.asMonths = function () {
2331      return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
2332  };
2333
2334
2335  /************************************
2336      Default Lang
2337  ************************************/
2338
2339
2340  // Set default language, other languages will inherit from English.
2341  moment.lang('en', {
2342      ordinal : function (number) {
2343          var b = number % 10,
2344              output = (toInt(number % 100 / 10) === 1) ? 'th' :
2345              (b === 1) ? 'st' :
2346              (b === 2) ? 'nd' :
2347              (b === 3) ? 'rd' : 'th';
2348          return number + output;
2349      }
2350  });
2351
2352  /* EMBED_LANGUAGES */
2353
2354  /************************************
2355      Exposing Moment
2356  ************************************/
2357
2358  function makeGlobal(deprecate) {
2359      var warned = false, local_moment = moment;
2360      /*global ender:false */
2361      if (typeof ender !== 'undefined') {
2362          return;
2363      }
2364      // here, `this` means `window` in the browser, or `global` on the server
2365      // add `moment` as a global object via a string identifier,
2366      // for Closure Compiler "advanced" mode
2367      if (deprecate) {
2368          global.moment = function () {
2369              if (!warned && console && console.warn) {
2370                  warned = true;
2371                  console.warn(
2372                          "Accessing Moment through the global scope is " +
2373                          "deprecated, and will be removed in an upcoming " +
2374                          "release.");
2375              }
2376              return local_moment.apply(null, arguments);
2377          };
2378          extend(global.moment, local_moment);
2379      } else {
2380          global['moment'] = moment;
2381      }
2382  }
2383
2384  // CommonJS module is defined
2385  if (hasModule) {
2386      module.exports = moment;
2387      makeGlobal(true);
2388  } else if (typeof define === "function" && define.amd) {
2389      define("moment", function (require, exports, module) {
2390          if (module.config && module.config() && module.config().noGlobal 
2390!== true) {
2391              // If user provided noGlobal, he is aware of global
2392              makeGlobal(module.config().noGlobal === undefined);
2393          }
2394
2395          return moment;
2396      });
2397  } else {
2398      makeGlobal();
2399  }
2400}).call(this);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.