[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/resources/lib/moment/ -> moment.js (source)

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


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1