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