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