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