summaryrefslogtreecommitdiff
path: root/js/components/datepicker.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/components/datepicker.js')
-rwxr-xr-xjs/components/datepicker.js3166
1 files changed, 0 insertions, 3166 deletions
diff --git a/js/components/datepicker.js b/js/components/datepicker.js
deleted file mode 100755
index 31890b4..0000000
--- a/js/components/datepicker.js
+++ /dev/null
@@ -1,3166 +0,0 @@
1/*! UIkit 2.26.4 | 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.isValid() ? active.current.format(active.options.format) : null).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 trying 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 strings 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});