GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

third-party/uikit/uikit-2.27.4/js/components/datepicker.js   F
last analyzed

Complexity

Total Complexity 610
Complexity/F 2.37

Size

Lines of Code 3167
Function Count 257

Duplication

Duplicated Lines 79
Ratio 2.49 %

Importance

Changes 0
Metric Value
eloc 1903
dl 79
loc 3167
rs 0.8
c 0
b 0
f 0
wmc 610
mnd 353
bc 353
fnc 257
bpm 1.3735
cpm 2.3735
noi 31

71 Functions

Rating   Name   Duplication   Size   Complexity  
A datepicker.js ➔ dateFromObject 0 20 2
C datepicker.js ➔ checkOverflow 0 19 9
F datepicker.js ➔ rawMonthSetter 0 17 163
A datepicker.js ➔ deprecate 0 10 3
A datepicker.js ➔ isLeapYear 0 3 1
B datepicker.js ➔ makeDateFromStringAndArray 0 44 6
A datepicker.js ➔ defaultParsingFlags 0 16 1
A datepicker.js ➔ rawSetter 0 7 3
A datepicker.js ➔ timezoneMinutesFromString 0 9 2
F datepicker.js ➔ makeDurationGetter 0 5 27
A datepicker.js ➔ Locale 0 2 3
A datepicker.js ➔ isDate 0 4 1
B datepicker.js ➔ dayOfYearFromWeekInfo 0 41 5
A datepicker.js ➔ makeDate 0 11 2
A datepicker.js ➔ extend 0 17 5
F datepicker.js ➔ dfl 0 7 119
A datepicker.js ➔ normalizeLocale 0 3 2
B datepicker.js ➔ makeList 0 41 8
A datepicker.js ➔ daysToYears 0 4 1
A datepicker.js ➔ leftZeroFill 0 9 4
A datepicker.js ➔ isArray 0 3 1
A datepicker.js ➔ makeDateFromString 0 7 2
A datepicker.js ➔ padToken 0 5 2
B datepicker.js ➔ dayOfYearFromWeeks 0 13 7
B datepicker.js ➔ makeMoment 0 28 6
A datepicker.js ➔ hasOwnProp 0 3 1
A datepicker.js ➔ makeAs 0 4 2
F datepicker.js ➔ removeFormattingTokens 0 6 40
A datepicker.js ➔ makeAccessor 0 11 3
A datepicker.js ➔ printMsg 0 6 2
A datepicker.js ➔ absRound 0 7 2
A datepicker.js ➔ map 0 7 2
A datepicker.js ➔ parseWeekday 0 14 4
A datepicker.js ➔ makeUTCDate 0 7 2
C datepicker.js ➔ getParseRegexForToken 0 86 8
D datepicker.js ➔ addTimeToArrayFromToken 0 133 10
B datepicker.js ➔ pickBy 0 16 8
A datepicker.js ➔ momentsDifference 0 13 2
A datepicker.js ➔ weekOfYear 0 20 3
A datepicker.js ➔ Moment 0 7 2
C datepicker.js ➔ dateFromConfig 0 48 11
A datepicker.js ➔ isValid 0 18 3
A datepicker.js ➔ normalizeUnits 0 7 2
C datepicker.js ➔ makeDateFromInput 0 24 9
A datepicker.js ➔ toInt 0 14 3
A datepicker.js ➔ unescapeFormat 0 5 2
A datepicker.js ➔ createAdder 0 15 4
A datepicker.js ➔ currentDateArray 0 12 2
A datepicker.js ➔ weeksInYear 0 3 1
F datepicker.js ➔ copyConfig 0 46 14
B datepicker.js ➔ addOrSubtractDurationFromMoment 0 19 6
A datepicker.js ➔ ordinalizeToken 0 5 2
A datepicker.js ➔ substituteTimeAgo 0 3 1
A datepicker.js ➔ relativeTime 0 25 1
A datepicker.js ➔ daysInYear 0 3 2
A datepicker.js ➔ loadLocale 0 12 3
B datepicker.js ➔ makeFormatFunction 0 19 6
A datepicker.js ➔ Duration 0 34 1
A datepicker.js ➔ daysInMonth 0 3 1
A datepicker.js ➔ regexpEscape 0 3 1
A datepicker.js ➔ rawGetter 0 3 2
A datepicker.js ➔ deprecateSimple 0 6 2
A datepicker.js ➔ expandFormat 0 16 3
A datepicker.js ➔ yearsToDays 0 5 1
A datepicker.js ➔ formatMoment 0 13 3
B datepicker.js ➔ parseISO 0 28 7
A datepicker.js ➔ normalizeObjectUnits 0 16 4
A datepicker.js ➔ positiveMomentsDifference 0 13 2
A datepicker.js ➔ compareArrays 13 13 3
B datepicker.js ➔ chooseLocale 23 23 6
C datepicker.js ➔ makeDateFromStringAndFormat 25 61 11

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like third-party/uikit/uikit-2.27.4/js/components/datepicker.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*! UIkit 2.27.4 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */
2
(function(addon) {
3
4
    var component;
5
6
    if (window.UIkit2) {
7
        component = addon(UIkit2);
8
    }
9
10
    if (typeof define == 'function' && define.amd) {
11
        define('uikit-datepicker', ['uikit'], function(){
12
            return component || addon(UIkit2);
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
            container: 'body',
39
            template: function(data, opts) {
40
41
                var content = '', i;
42
43
                content += '<div class="uk-datepicker-nav">';
44
                content += '<a href="" class="uk-datepicker-previous"></a>';
45
                content += '<a href="" class="uk-datepicker-next"></a>';
46
47
                if (UI.formSelect) {
48
49
                    var currentyear = (new Date()).getFullYear(), options = [], months, years, minYear, maxYear;
50
51
                    for (i=0;i<opts.i18n.months.length;i++) {
52
                        if(i==data.month) {
53
                            options.push('<option value="'+i+'" selected>'+opts.i18n.months[i]+'</option>');
54
                        } else {
55
                            options.push('<option value="'+i+'">'+opts.i18n.months[i]+'</option>');
56
                        }
57
                    }
58
59
                    months = '<span class="uk-form-select">'+ opts.i18n.months[data.month] + '<select class="update-picker-month">'+options.join('')+'</select></span>';
60
61
                    // --
62
63
                    options = [];
64
65
                    minYear = data.minDate ? data.minDate.year() : currentyear - 50;
66
                    maxYear = data.maxDate ? data.maxDate.year() : currentyear + 20;
67
68
                    for (i=minYear;i<=maxYear;i++) {
69
                        if (i == data.year) {
70
                            options.push('<option value="'+i+'" selected>'+i+'</option>');
71
                        } else {
72
                            options.push('<option value="'+i+'">'+i+'</option>');
73
                        }
74
                    }
75
76
                    years  = '<span class="uk-form-select">'+ data.year + '<select class="update-picker-year">'+options.join('')+'</select></span>';
77
78
                    content += '<div class="uk-datepicker-heading">'+ months + ' ' + years +'</div>';
79
80
                } else {
81
                    content += '<div class="uk-datepicker-heading">'+ opts.i18n.months[data.month] +' '+ data.year+'</div>';
82
                }
83
84
                content += '</div>';
85
86
                content += '<table class="uk-datepicker-table">';
87
                content += '<thead>';
88
                for(i = 0; i < data.weekdays.length; i++) {
89
                    if (data.weekdays[i]) {
90
                        content += '<th>'+data.weekdays[i]+'</th>';
91
                    }
92
                }
93
                content += '</thead>';
94
95
                content += '<tbody>';
96
                for(i = 0; i < data.days.length; i++) {
97
                    if (data.days[i] && data.days[i].length){
98
                        content += '<tr>';
99
                        for(var d = 0; d < data.days[i].length; d++) {
100
                            if (data.days[i][d]) {
101
                                var day = data.days[i][d],
102
                                    cls = [];
103
104
                                if(!day.inmonth) cls.push("uk-datepicker-table-muted");
105
                                if(day.selected) cls.push("uk-active");
106
                                if(day.disabled) cls.push('uk-datepicker-date-disabled uk-datepicker-table-muted');
107
108
                                content += '<td><a href="" class="'+cls.join(" ")+'" data-date="'+day.day.format()+'">'+day.day.format("D")+'</a></td>';
109
                            }
110
                        }
111
                        content += '</tr>';
112
                    }
113
                }
114
                content += '</tbody>';
115
116
                content += '</table>';
117
118
                return content;
119
            }
120
        },
121
122
        boot: function() {
123
124
            UI.$win.on('resize orientationchange', function() {
125
126
                if (active) {
127
                    active.hide();
128
                }
129
            });
130
131
            // init code
132
            UI.$html.on('focus.datepicker.uikit', '[data-uk-datepicker]', function(e) {
133
134
                var ele = UI.$(this);
135
136
                if (!ele.data('datepicker')) {
137
                    e.preventDefault();
138
                    UI.datepicker(ele, UI.Utils.options(ele.attr('data-uk-datepicker')));
139
                    ele.trigger('focus');
140
                }
141
            });
142
143
            UI.$html.on('click focus', '*', function(e) {
144
145
                var target = UI.$(e.target);
146
147
                if (active && target[0] != dropdown[0] && !target.data('datepicker') && !target.parents('.uk-datepicker:first').length) {
148
                    active.hide();
149
                }
150
            });
151
        },
152
153
        init: function() {
154
155
            // use native datepicker on touch devices
156
            if (UI.support.touch && this.element.attr('type')=='date' && !this.options.mobile) {
157
                return;
158
            }
159
160
            var $this = this;
161
162
            this.current  = this.element.val() ? moment(this.element.val(), this.options.format) : moment();
163
164
            this.on('click focus', function(){
165
                if (active!==$this) $this.pick(this.value ? this.value:'');
166
            }).on('change', function(){
167
168
                if ($this.element.val() && !moment($this.element.val(), $this.options.format).isValid()) {
169
                   $this.element.val(moment().format($this.options.format));
170
                }
171
            });
172
173
            // init dropdown
174
            if (!dropdown) {
175
176
                dropdown = UI.$('<div class="uk-dropdown uk-datepicker"></div>');
177
178
                dropdown.on('click', '.uk-datepicker-next, .uk-datepicker-previous, [data-date]', function(e){
179
180
                    e.stopPropagation();
181
                    e.preventDefault();
182
183
                    var ele = UI.$(this);
184
185
                    if (ele.hasClass('uk-datepicker-date-disabled')) return false;
186
187
                    if (ele.is('[data-date]')) {
188
                        active.current = moment(ele.data("date"));
189
                        active.element.val(active.current.isValid() ? active.current.format(active.options.format) : null).trigger("change");
190
                        active.hide();
191
                    } else {
192
                       active.add((ele.hasClass("uk-datepicker-next") ? 1:-1), "months");
193
                    }
194
                });
195
196
                dropdown.on('change', '.update-picker-month, .update-picker-year', function(){
197
198
                    var select = UI.$(this);
199
                    active[select.is('.update-picker-year') ? 'setYear':'setMonth'](Number(select.val()));
200
                });
201
202
                dropdown.appendTo(this.options.container);
203
            }
204
        },
205
206
        pick: function(initdate) {
207
208
            var offset = this.element.offset(),
209
                css    = {left: offset.left, right:''};
210
211
            this.current  = isNaN(initdate) ? moment(initdate, this.options.format):moment();
212
            this.initdate = this.current.format("YYYY-MM-DD");
213
214
            this.update();
215
216
            if (UI.langdirection == 'right') {
217
                css.right = window.innerWidth - (css.left + this.element.outerWidth());
218
                css.left  = '';
219
            }
220
221
            var posTop    = (offset.top - this.element.outerHeight() + this.element.height()) - this.options.offsettop - dropdown.outerHeight(),
222
                posBottom = offset.top + this.element.outerHeight() + this.options.offsettop;
223
224
            css.top = posBottom;
225
226
            if (this.options.pos == 'top') {
227
                css.top = posTop;
228
            } else if(this.options.pos == 'auto' && (window.innerHeight - posBottom - dropdown.outerHeight() < 0 && posTop >= 0) ) {
229
                css.top = posTop;
230
            }
231
232
            dropdown.css(css).show();
233
            this.trigger('show.uk.datepicker');
234
235
            active = this;
236
        },
237
238
        add: function(unit, value) {
239
            this.current.add(unit, value);
240
            this.update();
241
        },
242
243
        setMonth: function(month) {
244
            this.current.month(month);
245
            this.update();
246
        },
247
248
        setYear: function(year) {
249
            this.current.year(year);
250
            this.update();
251
        },
252
253
        update: function() {
254
255
            var data = this.getRows(this.current.year(), this.current.month()),
256
                tpl  = this.options.template(data, this.options);
257
258
            dropdown.html(tpl);
259
260
            this.trigger('update.uk.datepicker');
261
        },
262
263
        getRows: function(year, month) {
264
265
            var opts   = this.options,
266
                now    = moment().format('YYYY-MM-DD'),
267
                days   = [31, (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month],
268
                before = new Date(year, month, 1, 12).getDay(),
269
                data   = {month:month, year:year, weekdays:[], days:[], maxDate:false, minDate:false},
270
                row    = [];
271
272
            // We need these to be midday to avoid issues from DST transition protection.
273
            if (opts.maxDate!==false){
274
                data.maxDate = isNaN(opts.maxDate) ? moment(opts.maxDate, opts.format).startOf('day').hours(12) : moment().add(opts.maxDate, 'days').startOf('day').hours(12);
275
            }
276
277
            if (opts.minDate!==false){
278
                data.minDate = isNaN(opts.minDate) ? moment(opts.minDate, opts.format).startOf('day').hours(12) : moment().add(opts.minDate-1, 'days').startOf('day').hours(12);
279
            }
280
281
            data.weekdays = (function(){
282
283
                for (var i=0, arr=[]; i < 7; i++) {
284
285
                    var day = i + (opts.weekstart || 0);
286
287
                    while (day >= 7) {
288
                        day -= 7;
289
                    }
290
291
                    arr.push(opts.i18n.weekdays[day]);
292
                }
293
294
                return arr;
295
            })();
296
297
            if (opts.weekstart && opts.weekstart > 0) {
298
                before -= opts.weekstart;
299
                if (before < 0) {
300
                    before += 7;
301
                }
302
            }
303
304
            var cells = days + before, after = cells;
305
306
            while(after > 7) { after -= 7; }
307
308
            cells += 7 - after;
309
310
            var day, isDisabled, isSelected, isToday, isInMonth;
311
312
            for (var i = 0, r = 0; i < cells; i++) {
313
314
                day        = new Date(year, month, 1 + (i - before), 12);
315
                isDisabled = (data.minDate && data.minDate > day) || (data.maxDate && day > data.maxDate);
316
                isInMonth  = !(i < before || i >= (days + before));
317
318
                day = moment(day);
319
320
                isSelected = this.initdate == day.format('YYYY-MM-DD');
321
                isToday    = now == day.format('YYYY-MM-DD');
322
323
                row.push({selected: isSelected, today: isToday, disabled: isDisabled, day:day, inmonth:isInMonth});
324
325
                if (++r === 7) {
326
                    data.days.push(row);
327
                    row = [];
328
                    r = 0;
329
                }
330
            }
331
332
            return data;
333
        },
334
335
        hide: function() {
336
337
            if (active && active === this) {
338
                dropdown.hide();
339
                active = false;
340
341
                this.trigger('hide.uk.datepicker');
342
            }
343
        }
344
    });
345
346
    //! moment.js
347
    //! version : 2.8.3
348
    //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
349
    //! license : MIT
350
    //! momentjs.com
351
352
    moment = (function (undefined) {
353
        /************************************
354
            Constants
355
        ************************************/
356
        var moment,
357
            VERSION = '2.8.3',
358
            // the global-scope this is NOT the global object in Node.js
359
            globalScope = typeof global !== 'undefined' ? global : this,
0 ignored issues
show
Unused Code introduced by
The variable globalScope seems to be never used. Consider removing it.
Loading history...
360
            oldGlobalMoment,
0 ignored issues
show
Unused Code introduced by
The variable oldGlobalMoment seems to be never used. Consider removing it.
Loading history...
361
            round = Math.round,
362
            hasOwnProperty = Object.prototype.hasOwnProperty,
363
            i,
364
365
            YEAR = 0,
366
            MONTH = 1,
367
            DATE = 2,
368
            HOUR = 3,
369
            MINUTE = 4,
370
            SECOND = 5,
371
            MILLISECOND = 6,
372
373
            // internal storage for locale config files
374
            locales = {},
375
376
            // extra moment internal properties (plugins register props here)
377
            momentProperties = [],
378
379
            // check for nodeJS
380
            hasModule = (typeof module !== 'undefined' && module.exports),
381
382
            // ASP.NET json date format regex
383
            aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
384
            aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
385
386
            // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
387
            // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
388
            isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
389
390
            // format tokens
391
            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,
392
            localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
393
394
            // parsing token regexes
395
            parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
396
            parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
397
            parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999
398
            parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
399
            parseTokenDigits = /\d+/, // nonzero number of digits
400
            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.
401
            parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
402
            parseTokenT = /T/i, // T (ISO separator)
403
            parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
404
            parseTokenOrdinal = /\d{1,2}/,
405
406
            //strict parsing regexes
407
            parseTokenOneDigit = /\d/, // 0 - 9
408
            parseTokenTwoDigits = /\d\d/, // 00 - 99
409
            parseTokenThreeDigits = /\d{3}/, // 000 - 999
410
            parseTokenFourDigits = /\d{4}/, // 0000 - 9999
411
            parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999
412
            parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf
413
414
            // iso 8601 regex
415
            // 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)
416
            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)?)?$/,
417
418
            isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
419
420
            isoDates = [
421
                ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
422
                ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
423
                ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
424
                ['GGGG-[W]WW', /\d{4}-W\d{2}/],
425
                ['YYYY-DDD', /\d{4}-\d{3}/]
426
            ],
427
428
            // iso time formats and regexes
429
            isoTimes = [
430
                ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/],
431
                ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
432
                ['HH:mm', /(T| )\d\d:\d\d/],
433
                ['HH', /(T| )\d\d/]
434
            ],
435
436
            // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-15', '30']
437
            parseTimezoneChunker = /([\+\-]|\d\d)/gi,
438
439
            // getter and setter names
440
            proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
0 ignored issues
show
Unused Code introduced by
The variable proxyGettersAndSetters seems to be never used. Consider removing it.
Loading history...
441
            unitMillisecondFactors = {
442
                'Milliseconds' : 1,
443
                'Seconds' : 1e3,
444
                'Minutes' : 6e4,
445
                'Hours' : 36e5,
446
                'Days' : 864e5,
447
                'Months' : 2592e6,
448
                'Years' : 31536e6
449
            },
450
451
            unitAliases = {
452
                ms : 'millisecond',
453
                s : 'second',
454
                m : 'minute',
455
                h : 'hour',
456
                d : 'day',
457
                D : 'date',
458
                w : 'week',
459
                W : 'isoWeek',
460
                M : 'month',
461
                Q : 'quarter',
462
                y : 'year',
463
                DDD : 'dayOfYear',
464
                e : 'weekday',
465
                E : 'isoWeekday',
466
                gg: 'weekYear',
467
                GG: 'isoWeekYear'
468
            },
469
470
            camelFunctions = {
471
                dayofyear : 'dayOfYear',
472
                isoweekday : 'isoWeekday',
473
                isoweek : 'isoWeek',
474
                weekyear : 'weekYear',
475
                isoweekyear : 'isoWeekYear'
476
            },
477
478
            // format function strings
479
            formatFunctions = {},
480
481
            // default relative time thresholds
482
            relativeTimeThresholds = {
483
                s: 45,  // seconds to minute
484
                m: 45,  // minutes to hour
485
                h: 22,  // hours to day
486
                d: 26,  // days to month
487
                M: 11   // months to year
488
            },
489
490
            // tokens to ordinalize and pad
491
            ordinalizeTokens = 'DDD w W M D d'.split(' '),
492
            paddedTokens = 'M D H h m s w W'.split(' '),
493
494
            formatTokenFunctions = {
495
                M    : function () {
496
                    return this.month() + 1;
497
                },
498
                MMM  : function (format) {
499
                    return this.localeData().monthsShort(this, format);
500
                },
501
                MMMM : function (format) {
502
                    return this.localeData().months(this, format);
503
                },
504
                D    : function () {
505
                    return this.date();
506
                },
507
                DDD  : function () {
508
                    return this.dayOfYear();
509
                },
510
                d    : function () {
511
                    return this.day();
512
                },
513
                dd   : function (format) {
514
                    return this.localeData().weekdaysMin(this, format);
515
                },
516
                ddd  : function (format) {
517
                    return this.localeData().weekdaysShort(this, format);
518
                },
519
                dddd : function (format) {
520
                    return this.localeData().weekdays(this, format);
521
                },
522
                w    : function () {
523
                    return this.week();
524
                },
525
                W    : function () {
526
                    return this.isoWeek();
527
                },
528
                YY   : function () {
529
                    return leftZeroFill(this.year() % 100, 2);
530
                },
531
                YYYY : function () {
532
                    return leftZeroFill(this.year(), 4);
533
                },
534
                YYYYY : function () {
535
                    return leftZeroFill(this.year(), 5);
536
                },
537
                YYYYYY : function () {
538
                    var y = this.year(), sign = y >= 0 ? '+' : '-';
539
                    return sign + leftZeroFill(Math.abs(y), 6);
540
                },
541
                gg   : function () {
542
                    return leftZeroFill(this.weekYear() % 100, 2);
543
                },
544
                gggg : function () {
545
                    return leftZeroFill(this.weekYear(), 4);
546
                },
547
                ggggg : function () {
548
                    return leftZeroFill(this.weekYear(), 5);
549
                },
550
                GG   : function () {
551
                    return leftZeroFill(this.isoWeekYear() % 100, 2);
552
                },
553
                GGGG : function () {
554
                    return leftZeroFill(this.isoWeekYear(), 4);
555
                },
556
                GGGGG : function () {
557
                    return leftZeroFill(this.isoWeekYear(), 5);
558
                },
559
                e : function () {
560
                    return this.weekday();
561
                },
562
                E : function () {
563
                    return this.isoWeekday();
564
                },
565
                a    : function () {
566
                    return this.localeData().meridiem(this.hours(), this.minutes(), true);
567
                },
568
                A    : function () {
569
                    return this.localeData().meridiem(this.hours(), this.minutes(), false);
570
                },
571
                H    : function () {
572
                    return this.hours();
573
                },
574
                h    : function () {
575
                    return this.hours() % 12 || 12;
576
                },
577
                m    : function () {
578
                    return this.minutes();
579
                },
580
                s    : function () {
581
                    return this.seconds();
582
                },
583
                S    : function () {
584
                    return toInt(this.milliseconds() / 100);
585
                },
586
                SS   : function () {
587
                    return leftZeroFill(toInt(this.milliseconds() / 10), 2);
588
                },
589
                SSS  : function () {
590
                    return leftZeroFill(this.milliseconds(), 3);
591
                },
592
                SSSS : function () {
593
                    return leftZeroFill(this.milliseconds(), 3);
594
                },
595
                Z    : function () {
596
                    var a = -this.zone(),
597
                        b = '+';
598
                    if (a < 0) {
599
                        a = -a;
600
                        b = '-';
601
                    }
602
                    return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);
603
                },
604
                ZZ   : function () {
605
                    var a = -this.zone(),
606
                        b = '+';
607
                    if (a < 0) {
608
                        a = -a;
609
                        b = '-';
610
                    }
611
                    return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
612
                },
613
                z : function () {
614
                    return this.zoneAbbr();
615
                },
616
                zz : function () {
617
                    return this.zoneName();
618
                },
619
                X    : function () {
620
                    return this.unix();
621
                },
622
                Q : function () {
623
                    return this.quarter();
624
                }
625
            },
626
627
            deprecations = {},
628
629
            lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
630
631
        // Pick the first defined of two or three arguments. dfl comes from
632
        // default.
633
        function dfl(a, b, c) {
634
            switch (arguments.length) {
635
                case 2: return a != null ? a : b;
636
                case 3: return a != null ? a : b != null ? b : c;
637
                default: throw new Error('Implement me');
638
            }
639
        }
640
641
        function hasOwnProp(a, b) {
642
            return hasOwnProperty.call(a, b);
643
        }
644
645
        function defaultParsingFlags() {
646
            // We need to deep clone this object, and es5 standard is not very
647
            // helpful.
648
            return {
649
                empty : false,
650
                unusedTokens : [],
651
                unusedInput : [],
652
                overflow : -2,
653
                charsLeftOver : 0,
654
                nullInput : false,
655
                invalidMonth : null,
656
                invalidFormat : false,
657
                userInvalidated : false,
658
                iso: false
659
            };
660
        }
661
662
        function printMsg(msg) {
663
            if (moment.suppressDeprecationWarnings === false &&
664
                    typeof console !== 'undefined' && console.warn) {
665
                console.warn('Deprecation warning: ' + msg);
666
            }
667
        }
668
669
        function deprecate(msg, fn) {
670
            var firstTime = true;
671
            return extend(function () {
672
                if (firstTime) {
673
                    printMsg(msg);
674
                    firstTime = false;
675
                }
676
                return fn.apply(this, arguments);
677
            }, fn);
678
        }
679
680
        function deprecateSimple(name, msg) {
681
            if (!deprecations[name]) {
682
                printMsg(msg);
683
                deprecations[name] = true;
684
            }
685
        }
686
687
        function padToken(func, count) {
688
            return function (a) {
689
                return leftZeroFill(func.call(this, a), count);
690
            };
691
        }
692
        function ordinalizeToken(func, period) {
693
            return function (a) {
694
                return this.localeData().ordinal(func.call(this, a), period);
695
            };
696
        }
697
698
        while (ordinalizeTokens.length) {
699
            i = ordinalizeTokens.pop();
700
            formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
701
        }
702
        while (paddedTokens.length) {
703
            i = paddedTokens.pop();
704
            formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
705
        }
706
        formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
707
708
709
        /************************************
710
            Constructors
711
        ************************************/
712
713
        function Locale() {
714
        }
715
716
        // Moment prototype object
717
        function Moment(config, skipOverflow) {
718
            if (skipOverflow !== false) {
719
                checkOverflow(config);
720
            }
721
            copyConfig(this, config);
722
            this._d = new Date(+config._d);
723
        }
724
725
        // Duration Constructor
726
        function Duration(duration) {
727
            var normalizedInput = normalizeObjectUnits(duration),
728
                years = normalizedInput.year || 0,
729
                quarters = normalizedInput.quarter || 0,
730
                months = normalizedInput.month || 0,
731
                weeks = normalizedInput.week || 0,
732
                days = normalizedInput.day || 0,
733
                hours = normalizedInput.hour || 0,
734
                minutes = normalizedInput.minute || 0,
735
                seconds = normalizedInput.second || 0,
736
                milliseconds = normalizedInput.millisecond || 0;
737
738
            // representation for dateAddRemove
739
            this._milliseconds = +milliseconds +
740
                seconds * 1e3 + // 1000
741
                minutes * 6e4 + // 1000 * 60
742
                hours * 36e5; // 1000 * 60 * 60
743
            // Because of dateAddRemove treats 24 hours as different from a
744
            // day when working around DST, we need to store them separately
745
            this._days = +days +
746
                weeks * 7;
747
            // It is impossible translate months into days without knowing
748
            // which months you are are talking about, so we have to store
749
            // it separately.
750
            this._months = +months +
751
                quarters * 3 +
752
                years * 12;
753
754
            this._data = {};
755
756
            this._locale = moment.localeData();
757
758
            this._bubble();
759
        }
760
761
        /************************************
762
            Helpers
763
        ************************************/
764
765
766
        function extend(a, b) {
767
            for (var i in b) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
768
                if (hasOwnProp(b, i)) {
769
                    a[i] = b[i];
770
                }
771
            }
772
773
            if (hasOwnProp(b, 'toString')) {
774
                a.toString = b.toString;
775
            }
776
777
            if (hasOwnProp(b, 'valueOf')) {
778
                a.valueOf = b.valueOf;
779
            }
780
781
            return a;
782
        }
783
784
        function copyConfig(to, from) {
785
            var i, prop, val;
786
787
            if (typeof from._isAMomentObject !== 'undefined') {
788
                to._isAMomentObject = from._isAMomentObject;
789
            }
790
            if (typeof from._i !== 'undefined') {
791
                to._i = from._i;
792
            }
793
            if (typeof from._f !== 'undefined') {
794
                to._f = from._f;
795
            }
796
            if (typeof from._l !== 'undefined') {
797
                to._l = from._l;
798
            }
799
            if (typeof from._strict !== 'undefined') {
800
                to._strict = from._strict;
801
            }
802
            if (typeof from._tzm !== 'undefined') {
803
                to._tzm = from._tzm;
804
            }
805
            if (typeof from._isUTC !== 'undefined') {
806
                to._isUTC = from._isUTC;
807
            }
808
            if (typeof from._offset !== 'undefined') {
809
                to._offset = from._offset;
810
            }
811
            if (typeof from._pf !== 'undefined') {
812
                to._pf = from._pf;
813
            }
814
            if (typeof from._locale !== 'undefined') {
815
                to._locale = from._locale;
816
            }
817
818
            if (momentProperties.length > 0) {
819
                for (i in momentProperties) {
820
                    prop = momentProperties[i];
821
                    val = from[prop];
822
                    if (typeof val !== 'undefined') {
823
                        to[prop] = val;
824
                    }
825
                }
826
            }
827
828
            return to;
829
        }
830
831
        function absRound(number) {
832
            if (number < 0) {
833
                return Math.ceil(number);
834
            } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
835
                return Math.floor(number);
836
            }
837
        }
838
839
        // left zero fill a number
840
        // see http://jsperf.com/left-zero-filling for performance comparison
841
        function leftZeroFill(number, targetLength, forceSign) {
842
            var output = '' + Math.abs(number),
843
                sign = number >= 0;
844
845
            while (output.length < targetLength) {
846
                output = '0' + output;
847
            }
848
            return (sign ? (forceSign ? '+' : '') : '-') + output;
849
        }
850
851
        function positiveMomentsDifference(base, other) {
852
            var res = {milliseconds: 0, months: 0};
853
854
            res.months = other.month() - base.month() +
855
                (other.year() - base.year()) * 12;
856
            if (base.clone().add(res.months, 'M').isAfter(other)) {
857
                --res.months;
858
            }
859
860
            res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
861
862
            return res;
863
        }
864
865
        function momentsDifference(base, other) {
866
            var res;
867
            other = makeAs(other, base);
868
            if (base.isBefore(other)) {
869
                res = positiveMomentsDifference(base, other);
870
            } else {
871
                res = positiveMomentsDifference(other, base);
872
                res.milliseconds = -res.milliseconds;
873
                res.months = -res.months;
874
            }
875
876
            return res;
877
        }
878
879
        // TODO: remove 'name' arg after deprecation is removed
880
        function createAdder(direction, name) {
881
            return function (val, period) {
882
                var dur, tmp;
883
                //invert the arguments, but complain about it
884
                if (period !== null && !isNaN(+period)) {
885
                    deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
886
                    tmp = val; val = period; period = tmp;
887
                }
888
889
                val = typeof val === 'string' ? +val : val;
890
                dur = moment.duration(val, period);
891
                addOrSubtractDurationFromMoment(this, dur, direction);
892
                return this;
893
            };
894
        }
895
896
        function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
897
            var milliseconds = duration._milliseconds,
898
                days = duration._days,
899
                months = duration._months;
900
            updateOffset = updateOffset == null ? true : updateOffset;
901
902
            if (milliseconds) {
903
                mom._d.setTime(+mom._d + milliseconds * isAdding);
904
            }
905
            if (days) {
906
                rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);
907
            }
908
            if (months) {
909
                rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);
910
            }
911
            if (updateOffset) {
912
                moment.updateOffset(mom, days || months);
913
            }
914
        }
915
916
        // check if is an array
917
        function isArray(input) {
918
            return Object.prototype.toString.call(input) === '[object Array]';
919
        }
920
921
        function isDate(input) {
922
            return Object.prototype.toString.call(input) === '[object Date]' ||
923
                input instanceof Date;
924
        }
925
926
        // compare two arrays, return the number of differences
927 View Code Duplication
        function compareArrays(array1, array2, dontConvert) {
928
            var len = Math.min(array1.length, array2.length),
929
                lengthDiff = Math.abs(array1.length - array2.length),
930
                diffs = 0,
931
                i;
932
            for (i = 0; i < len; i++) {
933
                if ((dontConvert && array1[i] !== array2[i]) ||
934
                    (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
935
                    diffs++;
936
                }
937
            }
938
            return diffs + lengthDiff;
939
        }
940
941
        function normalizeUnits(units) {
942
            if (units) {
943
                var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
944
                units = unitAliases[units] || camelFunctions[lowered] || lowered;
945
            }
946
            return units;
947
        }
948
949
        function normalizeObjectUnits(inputObject) {
950
            var normalizedInput = {},
951
                normalizedProp,
952
                prop;
953
954
            for (prop in inputObject) {
955
                if (hasOwnProp(inputObject, prop)) {
956
                    normalizedProp = normalizeUnits(prop);
957
                    if (normalizedProp) {
958
                        normalizedInput[normalizedProp] = inputObject[prop];
959
                    }
960
                }
961
            }
962
963
            return normalizedInput;
964
        }
965
966
        function makeList(field) {
967
            var count, setter;
968
969
            if (field.indexOf('week') === 0) {
970
                count = 7;
971
                setter = 'day';
972
            }
973
            else if (field.indexOf('month') === 0) {
974
                count = 12;
975
                setter = 'month';
976
            }
977
            else {
978
                return;
979
            }
980
981
            moment[field] = function (format, index) {
982
                var i, getter,
983
                    method = moment._locale[field],
984
                    results = [];
985
986
                if (typeof format === 'number') {
987
                    index = format;
988
                    format = undefined;
989
                }
990
991
                getter = function (i) {
992
                    var m = moment().utc().set(setter, i);
993
                    return method.call(moment._locale, m, format || '');
994
                };
995
996
                if (index != null) {
997
                    return getter(index);
998
                }
999
                else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1000
                    for (i = 0; i < count; i++) {
1001
                        results.push(getter(i));
1002
                    }
1003
                    return results;
1004
                }
1005
            };
1006
        }
1007
1008
        function toInt(argumentForCoercion) {
1009
            var coercedNumber = +argumentForCoercion,
1010
                value = 0;
1011
1012
            if (coercedNumber !== 0 && isFinite(coercedNumber)) {
1013
                if (coercedNumber >= 0) {
1014
                    value = Math.floor(coercedNumber);
1015
                } else {
1016
                    value = Math.ceil(coercedNumber);
1017
                }
1018
            }
1019
1020
            return value;
1021
        }
1022
1023
        function daysInMonth(year, month) {
1024
            return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
1025
        }
1026
1027
        function weeksInYear(year, dow, doy) {
1028
            return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;
1029
        }
1030
1031
        function daysInYear(year) {
1032
            return isLeapYear(year) ? 366 : 365;
1033
        }
1034
1035
        function isLeapYear(year) {
1036
            return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
1037
        }
1038
1039
        function checkOverflow(m) {
1040
            var overflow;
1041
            if (m._a && m._pf.overflow === -2) {
1042
                overflow =
1043
                    m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
1044
                    m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
1045
                    m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
1046
                    m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
1047
                    m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
1048
                    m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
1049
                    -1;
1050
1051
                if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
1052
                    overflow = DATE;
1053
                }
1054
1055
                m._pf.overflow = overflow;
1056
            }
1057
        }
1058
1059
        function isValid(m) {
1060
            if (m._isValid == null) {
1061
                m._isValid = !isNaN(m._d.getTime()) &&
1062
                    m._pf.overflow < 0 &&
1063
                    !m._pf.empty &&
1064
                    !m._pf.invalidMonth &&
1065
                    !m._pf.nullInput &&
1066
                    !m._pf.invalidFormat &&
1067
                    !m._pf.userInvalidated;
1068
1069
                if (m._strict) {
1070
                    m._isValid = m._isValid &&
1071
                        m._pf.charsLeftOver === 0 &&
1072
                        m._pf.unusedTokens.length === 0;
1073
                }
1074
            }
1075
            return m._isValid;
1076
        }
1077
1078
        function normalizeLocale(key) {
1079
            return key ? key.toLowerCase().replace('_', '-') : key;
1080
        }
1081
1082
        // pick the locale from the array
1083
        // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
1084
        // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
1085 View Code Duplication
        function chooseLocale(names) {
1086
            var i = 0, j, next, locale, split;
1087
1088
            while (i < names.length) {
1089
                split = normalizeLocale(names[i]).split('-');
1090
                j = split.length;
1091
                next = normalizeLocale(names[i + 1]);
1092
                next = next ? next.split('-') : null;
1093
                while (j > 0) {
1094
                    locale = loadLocale(split.slice(0, j).join('-'));
1095
                    if (locale) {
1096
                        return locale;
1097
                    }
1098
                    if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
1099
                        //the next array item is better than a shallower substring of this one
1100
                        break;
1101
                    }
1102
                    j--;
1103
                }
1104
                i++;
1105
            }
1106
            return null;
1107
        }
1108
1109
        function loadLocale(name) {
1110
            var oldLocale = null;
0 ignored issues
show
Unused Code introduced by
The assignment to oldLocale seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
1111
            if (!locales[name] && hasModule) {
1112
                try {
1113
                    oldLocale = moment.locale();
1114
                    require('./locale/' + name);
1115
                    // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales
1116
                    moment.locale(oldLocale);
1117
                } catch (e) { }
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
1118
            }
1119
            return locales[name];
1120
        }
1121
1122
        // Return a moment from input, that is local/utc/zone equivalent to model.
1123
        function makeAs(input, model) {
1124
            return model._isUTC ? moment(input).zone(model._offset || 0) :
1125
                moment(input).local();
1126
        }
1127
1128
        /************************************
1129
            Locale
1130
        ************************************/
1131
1132
1133
        extend(Locale.prototype, {
1134
1135
            set : function (config) {
1136
                var prop, i;
1137
                for (i in config) {
1138
                    prop = config[i];
1139
                    if (typeof prop === 'function') {
1140
                        this[i] = prop;
1141
                    } else {
1142
                        this['_' + i] = prop;
1143
                    }
1144
                }
1145
            },
1146
1147
            _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
1148
            months : function (m) {
1149
                return this._months[m.month()];
1150
            },
1151
1152
            _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
1153
            monthsShort : function (m) {
1154
                return this._monthsShort[m.month()];
1155
            },
1156
1157
            monthsParse : function (monthName) {
1158
                var i, mom, regex;
1159
1160
                if (!this._monthsParse) {
1161
                    this._monthsParse = [];
1162
                }
1163
1164
                for (i = 0; i < 12; i++) {
1165
                    // make the regex if we don't have it already
1166
                    if (!this._monthsParse[i]) {
1167
                        mom = moment.utc([2000, i]);
1168
                        regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
1169
                        this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
1170
                    }
1171
                    // test the regex
1172
                    if (this._monthsParse[i].test(monthName)) {
1173
                        return i;
1174
                    }
1175
                }
1176
            },
1177
1178
            _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
1179
            weekdays : function (m) {
1180
                return this._weekdays[m.day()];
1181
            },
1182
1183
            _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
1184
            weekdaysShort : function (m) {
1185
                return this._weekdaysShort[m.day()];
1186
            },
1187
1188
            _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
1189
            weekdaysMin : function (m) {
1190
                return this._weekdaysMin[m.day()];
1191
            },
1192
1193
            weekdaysParse : function (weekdayName) {
1194
                var i, mom, regex;
1195
1196
                if (!this._weekdaysParse) {
1197
                    this._weekdaysParse = [];
1198
                }
1199
1200
                for (i = 0; i < 7; i++) {
1201
                    // make the regex if we don't have it already
1202
                    if (!this._weekdaysParse[i]) {
1203
                        mom = moment([2000, 1]).day(i);
1204
                        regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
1205
                        this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
1206
                    }
1207
                    // test the regex
1208
                    if (this._weekdaysParse[i].test(weekdayName)) {
1209
                        return i;
1210
                    }
1211
                }
1212
            },
1213
1214
            _longDateFormat : {
1215
                LT : 'h:mm A',
1216
                L : 'MM/DD/YYYY',
1217
                LL : 'MMMM D, YYYY',
1218
                LLL : 'MMMM D, YYYY LT',
1219
                LLLL : 'dddd, MMMM D, YYYY LT'
1220
            },
1221
            longDateFormat : function (key) {
1222
                var output = this._longDateFormat[key];
1223
                if (!output && this._longDateFormat[key.toUpperCase()]) {
1224
                    output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
1225
                        return val.slice(1);
1226
                    });
1227
                    this._longDateFormat[key] = output;
1228
                }
1229
                return output;
1230
            },
1231
1232
            isPM : function (input) {
1233
                // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
1234
                // Using charAt should be more compatible.
1235
                return ((input + '').toLowerCase().charAt(0) === 'p');
1236
            },
1237
1238
            _meridiemParse : /[ap]\.?m?\.?/i,
1239
            meridiem : function (hours, minutes, isLower) {
1240
                if (hours > 11) {
1241
                    return isLower ? 'pm' : 'PM';
1242
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1243
                    return isLower ? 'am' : 'AM';
1244
                }
1245
            },
1246
1247
            _calendar : {
1248
                sameDay : '[Today at] LT',
1249
                nextDay : '[Tomorrow at] LT',
1250
                nextWeek : 'dddd [at] LT',
1251
                lastDay : '[Yesterday at] LT',
1252
                lastWeek : '[Last] dddd [at] LT',
1253
                sameElse : 'L'
1254
            },
1255
            calendar : function (key, mom) {
1256
                var output = this._calendar[key];
1257
                return typeof output === 'function' ? output.apply(mom) : output;
1258
            },
1259
1260
            _relativeTime : {
1261
                future : 'in %s',
1262
                past : '%s ago',
1263
                s : 'a few seconds',
1264
                m : 'a minute',
1265
                mm : '%d minutes',
1266
                h : 'an hour',
1267
                hh : '%d hours',
1268
                d : 'a day',
1269
                dd : '%d days',
1270
                M : 'a month',
1271
                MM : '%d months',
1272
                y : 'a year',
1273
                yy : '%d years'
1274
            },
1275
1276
            relativeTime : function (number, withoutSuffix, string, isFuture) {
1277
                var output = this._relativeTime[string];
1278
                return (typeof output === 'function') ?
1279
                    output(number, withoutSuffix, string, isFuture) :
1280
                    output.replace(/%d/i, number);
1281
            },
1282
1283
            pastFuture : function (diff, output) {
1284
                var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
1285
                return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
1286
            },
1287
1288
            ordinal : function (number) {
1289
                return this._ordinal.replace('%d', number);
1290
            },
1291
            _ordinal : '%d',
1292
1293
            preparse : function (string) {
1294
                return string;
1295
            },
1296
1297
            postformat : function (string) {
1298
                return string;
1299
            },
1300
1301
            week : function (mom) {
1302
                return weekOfYear(mom, this._week.dow, this._week.doy).week;
1303
            },
1304
1305
            _week : {
1306
                dow : 0, // Sunday is the first day of the week.
1307
                doy : 6  // The week that contains Jan 1st is the first week of the year.
1308
            },
1309
1310
            _invalidDate: 'Invalid date',
1311
            invalidDate: function () {
1312
                return this._invalidDate;
1313
            }
1314
        });
1315
1316
        /************************************
1317
            Formatting
1318
        ************************************/
1319
1320
1321
        function removeFormattingTokens(input) {
1322
            if (input.match(/\[[\s\S]/)) {
1323
                return input.replace(/^\[|\]$/g, '');
1324
            }
1325
            return input.replace(/\\/g, '');
1326
        }
1327
1328
        function makeFormatFunction(format) {
1329
            var array = format.match(formattingTokens), i, length;
1330
1331
            for (i = 0, length = array.length; i < length; i++) {
1332
                if (formatTokenFunctions[array[i]]) {
1333
                    array[i] = formatTokenFunctions[array[i]];
1334
                } else {
1335
                    array[i] = removeFormattingTokens(array[i]);
1336
                }
1337
            }
1338
1339
            return function (mom) {
1340
                var output = '';
1341
                for (i = 0; i < length; i++) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 1341. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1342
                    output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
1343
                }
1344
                return output;
1345
            };
1346
        }
1347
1348
        // format date using native date object
1349
        function formatMoment(m, format) {
1350
            if (!m.isValid()) {
1351
                return m.localeData().invalidDate();
1352
            }
1353
1354
            format = expandFormat(format, m.localeData());
1355
1356
            if (!formatFunctions[format]) {
1357
                formatFunctions[format] = makeFormatFunction(format);
1358
            }
1359
1360
            return formatFunctions[format](m);
1361
        }
1362
1363
        function expandFormat(format, locale) {
1364
            var i = 5;
1365
1366
            function replaceLongDateFormatTokens(input) {
1367
                return locale.longDateFormat(input) || input;
1368
            }
1369
1370
            localFormattingTokens.lastIndex = 0;
1371
            while (i >= 0 && localFormattingTokens.test(format)) {
1372
                format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
1373
                localFormattingTokens.lastIndex = 0;
1374
                i -= 1;
1375
            }
1376
1377
            return format;
1378
        }
1379
1380
1381
        /************************************
1382
            Parsing
1383
        ************************************/
1384
1385
1386
        // get the regex to find the next token
1387
        function getParseRegexForToken(token, config) {
1388
            var a, strict = config._strict;
1389
            switch (token) {
1390
            case 'Q':
1391
                return parseTokenOneDigit;
1392
            case 'DDDD':
1393
                return parseTokenThreeDigits;
1394
            case 'YYYY':
1395
            case 'GGGG':
1396
            case 'gggg':
1397
                return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
1398
            case 'Y':
1399
            case 'G':
1400
            case 'g':
1401
                return parseTokenSignedNumber;
1402
            case 'YYYYYY':
1403
            case 'YYYYY':
1404
            case 'GGGGG':
1405
            case 'ggggg':
1406
                return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
1407
            case 'S':
1408
                if (strict) {
1409
                    return parseTokenOneDigit;
1410
                }
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
1411
                /* falls through */
1412
            case 'SS':
1413
                if (strict) {
1414
                    return parseTokenTwoDigits;
1415
                }
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
1416
                /* falls through */
1417
            case 'SSS':
1418
                if (strict) {
1419
                    return parseTokenThreeDigits;
1420
                }
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
1421
                /* falls through */
1422
            case 'DDD':
1423
                return parseTokenOneToThreeDigits;
1424
            case 'MMM':
1425
            case 'MMMM':
1426
            case 'dd':
1427
            case 'ddd':
1428
            case 'dddd':
1429
                return parseTokenWord;
1430
            case 'a':
1431
            case 'A':
1432
                return config._locale._meridiemParse;
1433
            case 'X':
1434
                return parseTokenTimestampMs;
1435
            case 'Z':
1436
            case 'ZZ':
1437
                return parseTokenTimezone;
1438
            case 'T':
1439
                return parseTokenT;
1440
            case 'SSSS':
1441
                return parseTokenDigits;
1442
            case 'MM':
1443
            case 'DD':
1444
            case 'YY':
1445
            case 'GG':
1446
            case 'gg':
1447
            case 'HH':
1448
            case 'hh':
1449
            case 'mm':
1450
            case 'ss':
1451
            case 'ww':
1452
            case 'WW':
1453
                return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
1454
            case 'M':
1455
            case 'D':
1456
            case 'd':
1457
            case 'H':
1458
            case 'h':
1459
            case 'm':
1460
            case 's':
1461
            case 'w':
1462
            case 'W':
1463
            case 'e':
1464
            case 'E':
1465
                return parseTokenOneOrTwoDigits;
1466
            case 'Do':
1467
                return parseTokenOrdinal;
1468
            default :
1469
                a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
0 ignored issues
show
Bug introduced by
The call to regexpEscape seems to have too many arguments starting with "i".
Loading history...
1470
                return a;
1471
            }
1472
        }
1473
1474
        function timezoneMinutesFromString(string) {
1475
            string = string || '';
1476
            var possibleTzMatches = (string.match(parseTokenTimezone) || []),
1477
                tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
1478
                parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
1479
                minutes = +(parts[1] * 60) + toInt(parts[2]);
1480
1481
            return parts[0] === '+' ? -minutes : minutes;
1482
        }
1483
1484
        // function to convert string input to date
1485
        function addTimeToArrayFromToken(token, input, config) {
1486
            var a, datePartArray = config._a;
1487
1488
            switch (token) {
1489
            // QUARTER
1490
            case 'Q':
1491
                if (input != null) {
1492
                    datePartArray[MONTH] = (toInt(input) - 1) * 3;
1493
                }
1494
                break;
1495
            // MONTH
1496
            case 'M' : // fall through to MM
1497
            case 'MM' :
1498
                if (input != null) {
1499
                    datePartArray[MONTH] = toInt(input) - 1;
1500
                }
1501
                break;
1502
            case 'MMM' : // fall through to MMMM
1503
            case 'MMMM' :
1504
                a = config._locale.monthsParse(input);
1505
                // if we didn't find a month name, mark the date as invalid.
1506
                if (a != null) {
1507
                    datePartArray[MONTH] = a;
1508
                } else {
1509
                    config._pf.invalidMonth = input;
1510
                }
1511
                break;
1512
            // DAY OF MONTH
1513
            case 'D' : // fall through to DD
1514
            case 'DD' :
1515
                if (input != null) {
1516
                    datePartArray[DATE] = toInt(input);
1517
                }
1518
                break;
1519
            case 'Do' :
1520
                if (input != null) {
1521
                    datePartArray[DATE] = toInt(parseInt(input, 10));
1522
                }
1523
                break;
1524
            // DAY OF YEAR
1525
            case 'DDD' : // fall through to DDDD
1526
            case 'DDDD' :
1527
                if (input != null) {
1528
                    config._dayOfYear = toInt(input);
1529
                }
1530
1531
                break;
1532
            // YEAR
1533
            case 'YY' :
1534
                datePartArray[YEAR] = moment.parseTwoDigitYear(input);
1535
                break;
1536
            case 'YYYY' :
1537
            case 'YYYYY' :
1538
            case 'YYYYYY' :
1539
                datePartArray[YEAR] = toInt(input);
1540
                break;
1541
            // AM / PM
1542
            case 'a' : // fall through to A
1543
            case 'A' :
1544
                config._isPm = config._locale.isPM(input);
1545
                break;
1546
            // 24 HOUR
1547
            case 'H' : // fall through to hh
1548
            case 'HH' : // fall through to hh
1549
            case 'h' : // fall through to hh
1550
            case 'hh' :
1551
                datePartArray[HOUR] = toInt(input);
1552
                break;
1553
            // MINUTE
1554
            case 'm' : // fall through to mm
1555
            case 'mm' :
1556
                datePartArray[MINUTE] = toInt(input);
1557
                break;
1558
            // SECOND
1559
            case 's' : // fall through to ss
1560
            case 'ss' :
1561
                datePartArray[SECOND] = toInt(input);
1562
                break;
1563
            // MILLISECOND
1564
            case 'S' :
1565
            case 'SS' :
1566
            case 'SSS' :
1567
            case 'SSSS' :
1568
                datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
1569
                break;
1570
            // UNIX TIMESTAMP WITH MS
1571
            case 'X':
1572
                config._d = new Date(parseFloat(input) * 1000);
1573
                break;
1574
            // TIMEZONE
1575
            case 'Z' : // fall through to ZZ
1576
            case 'ZZ' :
1577
                config._useUTC = true;
1578
                config._tzm = timezoneMinutesFromString(input);
1579
                break;
1580
            // WEEKDAY - human
1581
            case 'dd':
1582
            case 'ddd':
1583
            case 'dddd':
1584
                a = config._locale.weekdaysParse(input);
1585
                // if we didn't get a weekday name, mark the date as invalid
1586
                if (a != null) {
1587
                    config._w = config._w || {};
1588
                    config._w['d'] = a;
1589
                } else {
1590
                    config._pf.invalidWeekday = input;
1591
                }
1592
                break;
1593
            // WEEK, WEEK DAY - numeric
1594
            case 'w':
1595
            case 'ww':
1596
            case 'W':
1597
            case 'WW':
1598
            case 'd':
1599
            case 'e':
1600
            case 'E':
1601
                token = token.substr(0, 1);
1602
                /* falls through */
1603
            case 'gggg':
1604
            case 'GGGG':
1605
            case 'GGGGG':
1606
                token = token.substr(0, 2);
1607
                if (input) {
1608
                    config._w = config._w || {};
1609
                    config._w[token] = toInt(input);
1610
                }
1611
                break;
1612
            case 'gg':
1613
            case 'GG':
1614
                config._w = config._w || {};
1615
                config._w[token] = moment.parseTwoDigitYear(input);
1616
            }
1617
        }
1618
1619
        function dayOfYearFromWeekInfo(config) {
1620
            var w, weekYear, week, weekday, dow, doy, temp;
1621
1622
            w = config._w;
1623
            if (w.GG != null || w.W != null || w.E != null) {
1624
                dow = 1;
1625
                doy = 4;
1626
1627
                // TODO: We need to take the current isoWeekYear, but that depends on
1628
                // how we interpret now (local, utc, fixed offset). So create
1629
                // a now version of current config (take local/utc/offset flags, and
1630
                // create now).
1631
                weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year);
1632
                week = dfl(w.W, 1);
1633
                weekday = dfl(w.E, 1);
1634
            } else {
1635
                dow = config._locale._week.dow;
1636
                doy = config._locale._week.doy;
1637
1638
                weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);
1639
                week = dfl(w.w, 1);
1640
1641
                if (w.d != null) {
1642
                    // weekday -- low day numbers are considered next week
1643
                    weekday = w.d;
1644
                    if (weekday < dow) {
1645
                        ++week;
1646
                    }
1647
                } else if (w.e != null) {
1648
                    // local weekday -- counting starts from begining of week
1649
                    weekday = w.e + dow;
1650
                } else {
1651
                    // default to begining of week
1652
                    weekday = dow;
1653
                }
1654
            }
1655
            temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
1656
1657
            config._a[YEAR] = temp.year;
1658
            config._dayOfYear = temp.dayOfYear;
1659
        }
1660
1661
        // convert an array to a date.
1662
        // the array should mirror the parameters below
1663
        // note: all values past the year are optional and will default to the lowest possible value.
1664
        // [year, month, day , hour, minute, second, millisecond]
1665
        function dateFromConfig(config) {
1666
            var i, date, input = [], currentDate, yearToUse;
1667
1668
            if (config._d) {
1669
                return;
1670
            }
1671
1672
            currentDate = currentDateArray(config);
1673
1674
            //compute day of the year from weeks and weekdays
1675
            if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1676
                dayOfYearFromWeekInfo(config);
1677
            }
1678
1679
            //if the day of the year is set, figure out what it is
1680
            if (config._dayOfYear) {
1681
                yearToUse = dfl(config._a[YEAR], currentDate[YEAR]);
1682
1683
                if (config._dayOfYear > daysInYear(yearToUse)) {
1684
                    config._pf._overflowDayOfYear = true;
1685
                }
1686
1687
                date = makeUTCDate(yearToUse, 0, config._dayOfYear);
1688
                config._a[MONTH] = date.getUTCMonth();
1689
                config._a[DATE] = date.getUTCDate();
1690
            }
1691
1692
            // Default to current date.
1693
            // * if no year, month, day of month are given, default to today
1694
            // * if day of month is given, default month and year
1695
            // * if month is given, default only year
1696
            // * if year is given, don't default anything
1697
            for (i = 0; i < 3 && config._a[i] == null; ++i) {
1698
                config._a[i] = input[i] = currentDate[i];
1699
            }
1700
1701
            // Zero out whatever was not defaulted, including time
1702
            for (; i < 7; i++) {
1703
                config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1704
            }
1705
1706
            config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
1707
            // Apply timezone offset from input. The actual zone can be changed
1708
            // with parseZone.
1709
            if (config._tzm != null) {
1710
                config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm);
1711
            }
1712
        }
1713
1714
        function dateFromObject(config) {
1715
            var normalizedInput;
1716
1717
            if (config._d) {
1718
                return;
1719
            }
1720
1721
            normalizedInput = normalizeObjectUnits(config._i);
1722
            config._a = [
1723
                normalizedInput.year,
1724
                normalizedInput.month,
1725
                normalizedInput.day,
1726
                normalizedInput.hour,
1727
                normalizedInput.minute,
1728
                normalizedInput.second,
1729
                normalizedInput.millisecond
1730
            ];
1731
1732
            dateFromConfig(config);
1733
        }
1734
1735
        function currentDateArray(config) {
1736
            var now = new Date();
1737
            if (config._useUTC) {
1738
                return [
1739
                    now.getUTCFullYear(),
1740
                    now.getUTCMonth(),
1741
                    now.getUTCDate()
1742
                ];
1743
            } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
1744
                return [now.getFullYear(), now.getMonth(), now.getDate()];
1745
            }
1746
        }
1747
1748
        // date from string and format string
1749
        function makeDateFromStringAndFormat(config) {
1750
            if (config._f === moment.ISO_8601) {
1751
                parseISO(config);
1752
                return;
1753
            }
1754
1755
            config._a = [];
1756
            config._pf.empty = true;
1757
1758
            // This array is used to make a Date, either with `new Date` or `Date.UTC`
1759
            var string = '' + config._i,
1760
                i, parsedInput, tokens, token, skipped,
1761
                stringLength = string.length,
1762
                totalParsedInputLength = 0;
1763
1764
            tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
1765
1766 View Code Duplication
            for (i = 0; i < tokens.length; i++) {
1767
                token = tokens[i];
1768
                parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
1769
                if (parsedInput) {
1770
                    skipped = string.substr(0, string.indexOf(parsedInput));
1771
                    if (skipped.length > 0) {
1772
                        config._pf.unusedInput.push(skipped);
1773
                    }
1774
                    string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1775
                    totalParsedInputLength += parsedInput.length;
1776
                }
1777
                // don't parse if it's not a known token
1778
                if (formatTokenFunctions[token]) {
1779
                    if (parsedInput) {
1780
                        config._pf.empty = false;
1781
                    }
1782
                    else {
1783
                        config._pf.unusedTokens.push(token);
1784
                    }
1785
                    addTimeToArrayFromToken(token, parsedInput, config);
1786
                }
1787
                else if (config._strict && !parsedInput) {
1788
                    config._pf.unusedTokens.push(token);
1789
                }
1790
            }
1791
1792
            // add remaining unparsed input length to the string
1793
            config._pf.charsLeftOver = stringLength - totalParsedInputLength;
1794
            if (string.length > 0) {
1795
                config._pf.unusedInput.push(string);
1796
            }
1797
1798
            // handle am pm
1799
            if (config._isPm && config._a[HOUR] < 12) {
1800
                config._a[HOUR] += 12;
1801
            }
1802
            // if is 12 am, change hours to 0
1803
            if (config._isPm === false && config._a[HOUR] === 12) {
1804
                config._a[HOUR] = 0;
1805
            }
1806
1807
            dateFromConfig(config);
1808
            checkOverflow(config);
1809
        }
1810
1811
        function unescapeFormat(s) {
1812
            return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
1813
                return p1 || p2 || p3 || p4;
1814
            });
1815
        }
1816
1817
        // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1818
        function regexpEscape(s) {
1819
            return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1820
        }
1821
1822
        // date from string and array of format strings
1823
        function makeDateFromStringAndArray(config) {
1824
            var tempConfig,
1825
                bestMoment,
1826
1827
                scoreToBeat,
1828
                i,
1829
                currentScore;
1830
1831
            if (config._f.length === 0) {
1832
                config._pf.invalidFormat = true;
1833
                config._d = new Date(NaN);
1834
                return;
1835
            }
1836
1837
            for (i = 0; i < config._f.length; i++) {
1838
                currentScore = 0;
1839
                tempConfig = copyConfig({}, config);
1840
                if (config._useUTC != null) {
1841
                    tempConfig._useUTC = config._useUTC;
1842
                }
1843
                tempConfig._pf = defaultParsingFlags();
1844
                tempConfig._f = config._f[i];
1845
                makeDateFromStringAndFormat(tempConfig);
1846
1847
                if (!isValid(tempConfig)) {
1848
                    continue;
1849
                }
1850
1851
                // if there is any input that was not parsed add a penalty for that format
1852
                currentScore += tempConfig._pf.charsLeftOver;
1853
1854
                //or tokens
1855
                currentScore += tempConfig._pf.unusedTokens.length * 10;
1856
1857
                tempConfig._pf.score = currentScore;
1858
1859
                if (scoreToBeat == null || currentScore < scoreToBeat) {
1860
                    scoreToBeat = currentScore;
1861
                    bestMoment = tempConfig;
1862
                }
1863
            }
1864
1865
            extend(config, bestMoment || tempConfig);
1866
        }
1867
1868
        // date from iso format
1869
        function parseISO(config) {
1870
            var i, l,
1871
                string = config._i,
1872
                match = isoRegex.exec(string);
1873
1874
            if (match) {
1875
                config._pf.iso = true;
1876
                for (i = 0, l = isoDates.length; i < l; i++) {
1877
                    if (isoDates[i][1].exec(string)) {
1878
                        // match[5] should be 'T' or undefined
1879
                        config._f = isoDates[i][0] + (match[6] || ' ');
1880
                        break;
1881
                    }
1882
                }
1883
                for (i = 0, l = isoTimes.length; i < l; i++) {
1884
                    if (isoTimes[i][1].exec(string)) {
1885
                        config._f += isoTimes[i][0];
1886
                        break;
1887
                    }
1888
                }
1889
                if (string.match(parseTokenTimezone)) {
1890
                    config._f += 'Z';
1891
                }
1892
                makeDateFromStringAndFormat(config);
1893
            } else {
1894
                config._isValid = false;
1895
            }
1896
        }
1897
1898
        // date from iso format or fallback
1899
        function makeDateFromString(config) {
1900
            parseISO(config);
1901
            if (config._isValid === false) {
1902
                delete config._isValid;
1903
                moment.createFromInputFallback(config);
1904
            }
1905
        }
1906
1907
        function map(arr, fn) {
1908
            var res = [], i;
1909
            for (i = 0; i < arr.length; ++i) {
1910
                res.push(fn(arr[i], i));
1911
            }
1912
            return res;
1913
        }
1914
1915
        function makeDateFromInput(config) {
1916
            var input = config._i, matched;
1917
            if (input === undefined) {
1918
                config._d = new Date();
1919
            } else if (isDate(input)) {
1920
                config._d = new Date(+input);
1921
            } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {
1922
                config._d = new Date(+matched[1]);
1923
            } else if (typeof input === 'string') {
1924
                makeDateFromString(config);
1925
            } else if (isArray(input)) {
1926
                config._a = map(input.slice(0), function (obj) {
1927
                    return parseInt(obj, 10);
1928
                });
1929
                dateFromConfig(config);
1930
            } else if (typeof(input) === 'object') {
1931
                dateFromObject(config);
1932
            } else if (typeof(input) === 'number') {
1933
                // from milliseconds
1934
                config._d = new Date(input);
1935
            } else {
1936
                moment.createFromInputFallback(config);
1937
            }
1938
        }
1939
1940
        function makeDate(y, m, d, h, M, s, ms) {
1941
            //can't just apply() to create a date:
1942
            //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1943
            var date = new Date(y, m, d, h, M, s, ms);
1944
1945
            //the date constructor doesn't accept years < 1970
1946
            if (y < 1970) {
1947
                date.setFullYear(y);
1948
            }
1949
            return date;
1950
        }
1951
1952
        function makeUTCDate(y) {
1953
            var date = new Date(Date.UTC.apply(null, arguments));
1954
            if (y < 1970) {
1955
                date.setUTCFullYear(y);
1956
            }
1957
            return date;
1958
        }
1959
1960
        function parseWeekday(input, locale) {
1961
            if (typeof input === 'string') {
1962
                if (!isNaN(input)) {
1963
                    input = parseInt(input, 10);
1964
                }
1965
                else {
1966
                    input = locale.weekdaysParse(input);
1967
                    if (typeof input !== 'number') {
1968
                        return null;
1969
                    }
1970
                }
1971
            }
1972
            return input;
1973
        }
1974
1975
        /************************************
1976
            Relative Time
1977
        ************************************/
1978
1979
1980
        // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
1981
        function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
1982
            return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
1983
        }
1984
1985
        function relativeTime(posNegDuration, withoutSuffix, locale) {
1986
            var duration = moment.duration(posNegDuration).abs(),
1987
                seconds = round(duration.as('s')),
1988
                minutes = round(duration.as('m')),
1989
                hours = round(duration.as('h')),
1990
                days = round(duration.as('d')),
1991
                months = round(duration.as('M')),
1992
                years = round(duration.as('y')),
1993
1994
                args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
1995
                    minutes === 1 && ['m'] ||
1996
                    minutes < relativeTimeThresholds.m && ['mm', minutes] ||
1997
                    hours === 1 && ['h'] ||
1998
                    hours < relativeTimeThresholds.h && ['hh', hours] ||
1999
                    days === 1 && ['d'] ||
2000
                    days < relativeTimeThresholds.d && ['dd', days] ||
2001
                    months === 1 && ['M'] ||
2002
                    months < relativeTimeThresholds.M && ['MM', months] ||
2003
                    years === 1 && ['y'] || ['yy', years];
2004
2005
            args[2] = withoutSuffix;
2006
            args[3] = +posNegDuration > 0;
2007
            args[4] = locale;
2008
            return substituteTimeAgo.apply({}, args);
2009
        }
2010
2011
2012
        /************************************
2013
            Week of Year
2014
        ************************************/
2015
2016
2017
        // firstDayOfWeek       0 = sun, 6 = sat
2018
        //                      the day of the week that starts the week
2019
        //                      (usually sunday or monday)
2020
        // firstDayOfWeekOfYear 0 = sun, 6 = sat
2021
        //                      the first week is the week that contains the first
2022
        //                      of this day of the week
2023
        //                      (eg. ISO weeks use thursday (4))
2024
        function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
2025
            var end = firstDayOfWeekOfYear - firstDayOfWeek,
2026
                daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
2027
                adjustedMoment;
2028
2029
2030
            if (daysToDayOfWeek > end) {
2031
                daysToDayOfWeek -= 7;
2032
            }
2033
2034
            if (daysToDayOfWeek < end - 7) {
2035
                daysToDayOfWeek += 7;
2036
            }
2037
2038
            adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');
2039
            return {
2040
                week: Math.ceil(adjustedMoment.dayOfYear() / 7),
2041
                year: adjustedMoment.year()
2042
            };
2043
        }
2044
2045
        //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
2046
        function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
2047
            var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
2048
2049
            d = d === 0 ? 7 : d;
2050
            weekday = weekday != null ? weekday : firstDayOfWeek;
2051
            daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
2052
            dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
2053
2054
            return {
2055
                year: dayOfYear > 0 ? year : year - 1,
2056
                dayOfYear: dayOfYear > 0 ?  dayOfYear : daysInYear(year - 1) + dayOfYear
2057
            };
2058
        }
2059
2060
        /************************************
2061
            Top Level Functions
2062
        ************************************/
2063
2064
        function makeMoment(config) {
2065
            var input = config._i,
2066
                format = config._f;
2067
2068
            config._locale = config._locale || moment.localeData(config._l);
2069
2070
            if (input === null || (format === undefined && input === '')) {
2071
                return moment.invalid({nullInput: true});
2072
            }
2073
2074
            if (typeof input === 'string') {
2075
                config._i = input = config._locale.preparse(input);
2076
            }
2077
2078
            if (moment.isMoment(input)) {
2079
                return new Moment(input, true);
2080
            } else if (format) {
2081
                if (isArray(format)) {
2082
                    makeDateFromStringAndArray(config);
2083
                } else {
2084
                    makeDateFromStringAndFormat(config);
2085
                }
2086
            } else {
2087
                makeDateFromInput(config);
2088
            }
2089
2090
            return new Moment(config);
2091
        }
2092
2093
        moment = function (input, format, locale, strict) {
2094
            var c;
2095
2096
            if (typeof(locale) === 'boolean') {
2097
                strict = locale;
2098
                locale = undefined;
2099
            }
2100
            // object construction must be done this way.
2101
            // https://github.com/moment/moment/issues/1423
2102
            c = {};
2103
            c._isAMomentObject = true;
2104
            c._i = input;
2105
            c._f = format;
2106
            c._l = locale;
2107
            c._strict = strict;
2108
            c._isUTC = false;
2109
            c._pf = defaultParsingFlags();
2110
2111
            return makeMoment(c);
2112
        };
2113
2114
        moment.suppressDeprecationWarnings = false;
2115
2116
        moment.createFromInputFallback = deprecate(
2117
            'moment construction falls back to js Date. This is ' +
2118
            'discouraged and will be removed in upcoming major ' +
2119
            'release. Please refer to ' +
2120
            'https://github.com/moment/moment/issues/1407 for more info.',
2121
            function (config) {
2122
                config._d = new Date(config._i);
2123
            }
2124
        );
2125
2126
        // Pick a moment m from moments so that m[fn](other) is true for all
2127
        // other. This relies on the function fn to be transitive.
2128
        //
2129
        // moments should either be an array of moment objects or an array, whose
2130
        // first element is an array of moment objects.
2131
        function pickBy(fn, moments) {
2132
            var res, i;
2133
            if (moments.length === 1 && isArray(moments[0])) {
2134
                moments = moments[0];
2135
            }
2136
            if (!moments.length) {
2137
                return moment();
2138
            }
2139
            res = moments[0];
2140
            for (i = 1; i < moments.length; ++i) {
2141
                if (moments[i][fn](res)) {
2142
                    res = moments[i];
2143
                }
2144
            }
2145
            return res;
2146
        }
2147
2148
        moment.min = function () {
2149
            var args = [].slice.call(arguments, 0);
2150
2151
            return pickBy('isBefore', args);
2152
        };
2153
2154
        moment.max = function () {
2155
            var args = [].slice.call(arguments, 0);
2156
2157
            return pickBy('isAfter', args);
2158
        };
2159
2160
        // creating with utc
2161
        moment.utc = function (input, format, locale, strict) {
2162
            var c;
2163
2164
            if (typeof(locale) === 'boolean') {
2165
                strict = locale;
2166
                locale = undefined;
2167
            }
2168
            // object construction must be done this way.
2169
            // https://github.com/moment/moment/issues/1423
2170
            c = {};
2171
            c._isAMomentObject = true;
2172
            c._useUTC = true;
2173
            c._isUTC = true;
2174
            c._l = locale;
2175
            c._i = input;
2176
            c._f = format;
2177
            c._strict = strict;
2178
            c._pf = defaultParsingFlags();
2179
2180
            return makeMoment(c).utc();
2181
        };
2182
2183
        // creating with unix timestamp (in seconds)
2184
        moment.unix = function (input) {
2185
            return moment(input * 1000);
2186
        };
2187
2188
        // duration
2189
        moment.duration = function (input, key) {
2190
            var duration = input,
2191
                // matching against regexp is expensive, do it on demand
2192
                match = null,
0 ignored issues
show
Unused Code introduced by
The assignment to match seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
2193
                sign,
2194
                ret,
2195
                parseIso,
2196
                diffRes;
2197
2198
            if (moment.isDuration(input)) {
2199
                duration = {
2200
                    ms: input._milliseconds,
2201
                    d: input._days,
2202
                    M: input._months
2203
                };
2204
            } else if (typeof input === 'number') {
2205
                duration = {};
2206
                if (key) {
2207
                    duration[key] = input;
2208
                } else {
2209
                    duration.milliseconds = input;
2210
                }
2211
            } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
2212
                sign = (match[1] === '-') ? -1 : 1;
2213
                duration = {
2214
                    y: 0,
2215
                    d: toInt(match[DATE]) * sign,
2216
                    h: toInt(match[HOUR]) * sign,
2217
                    m: toInt(match[MINUTE]) * sign,
2218
                    s: toInt(match[SECOND]) * sign,
2219
                    ms: toInt(match[MILLISECOND]) * sign
2220
                };
2221
            } else if (!!(match = isoDurationRegex.exec(input))) {
2222
                sign = (match[1] === '-') ? -1 : 1;
2223
                parseIso = function (inp) {
2224
                    // We'd normally use ~~inp for this, but unfortunately it also
2225
                    // converts floats to ints.
2226
                    // inp may be undefined, so careful calling replace on it.
2227
                    var res = inp && parseFloat(inp.replace(',', '.'));
2228
                    // apply sign while we're at it
2229
                    return (isNaN(res) ? 0 : res) * sign;
2230
                };
2231
                duration = {
2232
                    y: parseIso(match[2]),
2233
                    M: parseIso(match[3]),
2234
                    d: parseIso(match[4]),
2235
                    h: parseIso(match[5]),
2236
                    m: parseIso(match[6]),
2237
                    s: parseIso(match[7]),
2238
                    w: parseIso(match[8])
2239
                };
2240
            } else if (typeof duration === 'object' &&
2241
                    ('from' in duration || 'to' in duration)) {
2242
                diffRes = momentsDifference(moment(duration.from), moment(duration.to));
2243
2244
                duration = {};
2245
                duration.ms = diffRes.milliseconds;
2246
                duration.M = diffRes.months;
2247
            }
2248
2249
            ret = new Duration(duration);
2250
2251
            if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {
2252
                ret._locale = input._locale;
2253
            }
2254
2255
            return ret;
2256
        };
2257
2258
        // version number
2259
        moment.version = VERSION;
2260
2261
        // default format
2262
        moment.defaultFormat = isoFormat;
2263
2264
        // constant that refers to the ISO standard
2265
        moment.ISO_8601 = function () {};
2266
2267
        // Plugins that add properties should also add the key here (null value),
2268
        // so we can properly clone ourselves.
2269
        moment.momentProperties = momentProperties;
2270
2271
        // This function will be called whenever a moment is mutated.
2272
        // It is intended to keep the offset in sync with the timezone.
2273
        moment.updateOffset = function () {};
2274
2275
        // This function allows you to set a threshold for relative time strings
2276
        moment.relativeTimeThreshold = function (threshold, limit) {
2277
            if (relativeTimeThresholds[threshold] === undefined) {
2278
                return false;
2279
            }
2280
            if (limit === undefined) {
2281
                return relativeTimeThresholds[threshold];
2282
            }
2283
            relativeTimeThresholds[threshold] = limit;
2284
            return true;
2285
        };
2286
2287
        moment.lang = deprecate(
2288
            'moment.lang is deprecated. Use moment.locale instead.',
2289
            function (key, value) {
2290
                return moment.locale(key, value);
2291
            }
2292
        );
2293
2294
        // This function will load locale and then set the global locale.  If
2295
        // no arguments are passed in, it will simply return the current global
2296
        // locale key.
2297
        moment.locale = function (key, values) {
2298
            var data;
2299
            if (key) {
2300
                if (typeof(values) !== 'undefined') {
2301
                    data = moment.defineLocale(key, values);
2302
                }
2303
                else {
2304
                    data = moment.localeData(key);
2305
                }
2306
2307
                if (data) {
2308
                    moment.duration._locale = moment._locale = data;
2309
                }
2310
            }
2311
2312
            return moment._locale._abbr;
2313
        };
2314
2315
        moment.defineLocale = function (name, values) {
2316
            if (values !== null) {
2317
                values.abbr = name;
2318
                if (!locales[name]) {
2319
                    locales[name] = new Locale();
2320
                }
2321
                locales[name].set(values);
2322
2323
                // backwards compat for now: also set the locale
2324
                moment.locale(name);
2325
2326
                return locales[name];
2327
            } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2328
                // useful for testing
2329
                delete locales[name];
2330
                return null;
2331
            }
2332
        };
2333
2334
        moment.langData = deprecate(
2335
            'moment.langData is deprecated. Use moment.localeData instead.',
2336
            function (key) {
2337
                return moment.localeData(key);
2338
            }
2339
        );
2340
2341
        // returns locale data
2342
        moment.localeData = function (key) {
2343
            var locale;
2344
2345
            if (key && key._locale && key._locale._abbr) {
2346
                key = key._locale._abbr;
2347
            }
2348
2349
            if (!key) {
2350
                return moment._locale;
2351
            }
2352
2353
            if (!isArray(key)) {
2354
                //short-circuit everything else
2355
                locale = loadLocale(key);
2356
                if (locale) {
2357
                    return locale;
2358
                }
2359
                key = [key];
2360
            }
2361
2362
            return chooseLocale(key);
2363
        };
2364
2365
        // compare moment object
2366
        moment.isMoment = function (obj) {
2367
            return obj instanceof Moment ||
2368
                (obj != null && hasOwnProp(obj, '_isAMomentObject'));
2369
        };
2370
2371
        // for typechecking Duration objects
2372
        moment.isDuration = function (obj) {
2373
            return obj instanceof Duration;
2374
        };
2375
2376
        for (i = lists.length - 1; i >= 0; --i) {
2377
            makeList(lists[i]);
2378
        }
2379
2380
        moment.normalizeUnits = function (units) {
2381
            return normalizeUnits(units);
2382
        };
2383
2384
        moment.invalid = function (flags) {
2385
            var m = moment.utc(NaN);
2386
            if (flags != null) {
2387
                extend(m._pf, flags);
2388
            }
2389
            else {
2390
                m._pf.userInvalidated = true;
2391
            }
2392
2393
            return m;
2394
        };
2395
2396
        moment.parseZone = function () {
2397
            return moment.apply(null, arguments).parseZone();
2398
        };
2399
2400
        moment.parseTwoDigitYear = function (input) {
2401
            return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
2402
        };
2403
2404
        /************************************
2405
            Moment Prototype
2406
        ************************************/
2407
2408
2409
        extend(moment.fn = Moment.prototype, {
2410
2411
            clone : function () {
2412
                return moment(this);
2413
            },
2414
2415
            valueOf : function () {
2416
                return +this._d + ((this._offset || 0) * 60000);
2417
            },
2418
2419
            unix : function () {
2420
                return Math.floor(+this / 1000);
2421
            },
2422
2423
            toString : function () {
2424
                return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
2425
            },
2426
2427
            toDate : function () {
2428
                return this._offset ? new Date(+this) : this._d;
2429
            },
2430
2431
            toISOString : function () {
2432
                var m = moment(this).utc();
2433
                if (0 < m.year() && m.year() <= 9999) {
2434
                    return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
2435
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2436
                    return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
2437
                }
2438
            },
2439
2440
            toArray : function () {
2441
                var m = this;
2442
                return [
2443
                    m.year(),
2444
                    m.month(),
2445
                    m.date(),
2446
                    m.hours(),
2447
                    m.minutes(),
2448
                    m.seconds(),
2449
                    m.milliseconds()
2450
                ];
2451
            },
2452
2453
            isValid : function () {
2454
                return isValid(this);
2455
            },
2456
2457
            isDSTShifted : function () {
2458
                if (this._a) {
2459
                    return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
2460
                }
2461
2462
                return false;
2463
            },
2464
2465
            parsingFlags : function () {
2466
                return extend({}, this._pf);
2467
            },
2468
2469
            invalidAt: function () {
2470
                return this._pf.overflow;
2471
            },
2472
2473
            utc : function (keepLocalTime) {
2474
                return this.zone(0, keepLocalTime);
2475
            },
2476
2477
            local : function (keepLocalTime) {
2478
                if (this._isUTC) {
2479
                    this.zone(0, keepLocalTime);
2480
                    this._isUTC = false;
2481
2482
                    if (keepLocalTime) {
2483
                        this.add(this._dateTzOffset(), 'm');
2484
                    }
2485
                }
2486
                return this;
2487
            },
2488
2489
            format : function (inputString) {
2490
                var output = formatMoment(this, inputString || moment.defaultFormat);
2491
                return this.localeData().postformat(output);
2492
            },
2493
2494
            add : createAdder(1, 'add'),
2495
2496
            subtract : createAdder(-1, 'subtract'),
2497
2498
            diff : function (input, units, asFloat) {
2499
                var that = makeAs(input, this),
2500
                    zoneDiff = (this.zone() - that.zone()) * 6e4,
2501
                    diff, output, daysAdjust;
2502
2503
                units = normalizeUnits(units);
2504
2505
                if (units === 'year' || units === 'month') {
2506
                    // average number of days in the months in the given dates
2507
                    diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
2508
                    // difference in months
2509
                    output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
2510
                    // adjust by taking difference in days, average number of days
2511
                    // and dst in the given months.
2512
                    daysAdjust = (this - moment(this).startOf('month')) -
2513
                        (that - moment(that).startOf('month'));
2514
                    // same as above but with zones, to negate all dst
2515
                    daysAdjust -= ((this.zone() - moment(this).startOf('month').zone()) -
2516
                            (that.zone() - moment(that).startOf('month').zone())) * 6e4;
2517
                    output += daysAdjust / diff;
2518
                    if (units === 'year') {
2519
                        output = output / 12;
2520
                    }
2521
                } else {
2522
                    diff = (this - that);
2523
                    output = units === 'second' ? diff / 1e3 : // 1000
2524
                        units === 'minute' ? diff / 6e4 : // 1000 * 60
2525
                        units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
2526
                        units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
2527
                        units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
2528
                        diff;
2529
                }
2530
                return asFloat ? output : absRound(output);
2531
            },
2532
2533
            from : function (time, withoutSuffix) {
2534
                return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
2535
            },
2536
2537
            fromNow : function (withoutSuffix) {
2538
                return this.from(moment(), withoutSuffix);
2539
            },
2540
2541
            calendar : function (time) {
2542
                // We want to compare the start of today, vs this.
2543
                // Getting start-of-today depends on whether we're zone'd or not.
2544
                var now = time || moment(),
2545
                    sod = makeAs(now, this).startOf('day'),
2546
                    diff = this.diff(sod, 'days', true),
2547
                    format = diff < -6 ? 'sameElse' :
2548
                        diff < -1 ? 'lastWeek' :
2549
                        diff < 0 ? 'lastDay' :
2550
                        diff < 1 ? 'sameDay' :
2551
                        diff < 2 ? 'nextDay' :
2552
                        diff < 7 ? 'nextWeek' : 'sameElse';
2553
                return this.format(this.localeData().calendar(format, this));
2554
            },
2555
2556
            isLeapYear : function () {
2557
                return isLeapYear(this.year());
2558
            },
2559
2560
            isDST : function () {
2561
                return (this.zone() < this.clone().month(0).zone() ||
2562
                    this.zone() < this.clone().month(5).zone());
2563
            },
2564
2565
            day : function (input) {
2566
                var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
2567
                if (input != null) {
2568
                    input = parseWeekday(input, this.localeData());
2569
                    return this.add(input - day, 'd');
2570
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2571
                    return day;
2572
                }
2573
            },
2574
2575
            month : makeAccessor('Month', true),
2576
2577
            startOf : function (units) {
2578
                units = normalizeUnits(units);
2579
                // the following switch intentionally omits break keywords
2580
                // to utilize falling through the cases.
2581
                switch (units) {
2582
                case 'year':
2583
                    this.month(0);
2584
                    /* falls through */
2585
                case 'quarter':
2586
                case 'month':
2587
                    this.date(1);
2588
                    /* falls through */
2589
                case 'week':
2590
                case 'isoWeek':
2591
                case 'day':
2592
                    this.hours(0);
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
2593
                    /* falls through */
2594
                case 'hour':
2595
                    this.minutes(0);
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
2596
                    /* falls through */
2597
                case 'minute':
2598
                    this.seconds(0);
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
2599
                    /* falls through */
2600
                case 'second':
2601
                    this.milliseconds(0);
2602
                    /* falls through */
2603
                }
2604
2605
                // weeks are a special case
2606
                if (units === 'week') {
2607
                    this.weekday(0);
2608
                } else if (units === 'isoWeek') {
2609
                    this.isoWeekday(1);
2610
                }
2611
2612
                // quarters are also special
2613
                if (units === 'quarter') {
2614
                    this.month(Math.floor(this.month() / 3) * 3);
2615
                }
2616
2617
                return this;
2618
            },
2619
2620
            endOf: function (units) {
2621
                units = normalizeUnits(units);
2622
                return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
2623
            },
2624
2625 View Code Duplication
            isAfter: function (input, units) {
2626
                units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
2627
                if (units === 'millisecond') {
2628
                    input = moment.isMoment(input) ? input : moment(input);
2629
                    return +this > +input;
2630
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2631
                    return +this.clone().startOf(units) > +moment(input).startOf(units);
2632
                }
2633
            },
2634
2635 View Code Duplication
            isBefore: function (input, units) {
2636
                units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
2637
                if (units === 'millisecond') {
2638
                    input = moment.isMoment(input) ? input : moment(input);
2639
                    return +this < +input;
2640
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2641
                    return +this.clone().startOf(units) < +moment(input).startOf(units);
2642
                }
2643
            },
2644
2645
            isSame: function (input, units) {
2646
                units = normalizeUnits(units || 'millisecond');
2647
                if (units === 'millisecond') {
2648
                    input = moment.isMoment(input) ? input : moment(input);
2649
                    return +this === +input;
2650
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2651
                    return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
2652
                }
2653
            },
2654
2655
            min: deprecate(
2656
                     'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
2657
                     function (other) {
2658
                         other = moment.apply(null, arguments);
2659
                         return other < this ? this : other;
2660
                     }
2661
             ),
2662
2663
            max: deprecate(
2664
                    'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
2665
                    function (other) {
2666
                        other = moment.apply(null, arguments);
2667
                        return other > this ? this : other;
2668
                    }
2669
            ),
2670
2671
            // keepLocalTime = true means only change the timezone, without
2672
            // affecting the local hour. So 5:31:26 +0300 --[zone(2, true)]-->
2673
            // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist int zone
2674
            // +0200, so we adjust the time as needed, to be valid.
2675
            //
2676
            // Keeping the time actually adds/subtracts (one hour)
2677
            // from the actual represented time. That is why we call updateOffset
2678
            // a second time. In case it wants us to change the offset again
2679
            // _changeInProgress == true case, then we have to adjust, because
2680
            // there is no such time in the given timezone.
2681
            zone : function (input, keepLocalTime) {
2682
                var offset = this._offset || 0,
2683
                    localAdjust;
2684
                if (input != null) {
2685
                    if (typeof input === 'string') {
2686
                        input = timezoneMinutesFromString(input);
2687
                    }
2688
                    if (Math.abs(input) < 16) {
2689
                        input = input * 60;
2690
                    }
2691
                    if (!this._isUTC && keepLocalTime) {
2692
                        localAdjust = this._dateTzOffset();
2693
                    }
2694
                    this._offset = input;
2695
                    this._isUTC = true;
2696
                    if (localAdjust != null) {
2697
                        this.subtract(localAdjust, 'm');
2698
                    }
2699
                    if (offset !== input) {
2700
                        if (!keepLocalTime || this._changeInProgress) {
2701
                            addOrSubtractDurationFromMoment(this,
2702
                                    moment.duration(offset - input, 'm'), 1, false);
2703
                        } else if (!this._changeInProgress) {
2704
                            this._changeInProgress = true;
2705
                            moment.updateOffset(this, true);
2706
                            this._changeInProgress = null;
2707
                        }
2708
                    }
2709
                } else {
2710
                    return this._isUTC ? offset : this._dateTzOffset();
2711
                }
2712
                return this;
2713
            },
2714
2715
            zoneAbbr : function () {
2716
                return this._isUTC ? 'UTC' : '';
2717
            },
2718
2719
            zoneName : function () {
2720
                return this._isUTC ? 'Coordinated Universal Time' : '';
2721
            },
2722
2723
            parseZone : function () {
2724
                if (this._tzm) {
2725
                    this.zone(this._tzm);
2726
                } else if (typeof this._i === 'string') {
2727
                    this.zone(this._i);
2728
                }
2729
                return this;
2730
            },
2731
2732
            hasAlignedHourOffset : function (input) {
2733
                if (!input) {
2734
                    input = 0;
2735
                }
2736
                else {
2737
                    input = moment(input).zone();
2738
                }
2739
2740
                return (this.zone() - input) % 60 === 0;
2741
            },
2742
2743
            daysInMonth : function () {
2744
                return daysInMonth(this.year(), this.month());
2745
            },
2746
2747
            dayOfYear : function (input) {
2748
                var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
2749
                return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
2750
            },
2751
2752
            quarter : function (input) {
2753
                return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
2754
            },
2755
2756
            weekYear : function (input) {
2757
                var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
2758
                return input == null ? year : this.add((input - year), 'y');
2759
            },
2760
2761
            isoWeekYear : function (input) {
2762
                var year = weekOfYear(this, 1, 4).year;
2763
                return input == null ? year : this.add((input - year), 'y');
2764
            },
2765
2766
            week : function (input) {
2767
                var week = this.localeData().week(this);
2768
                return input == null ? week : this.add((input - week) * 7, 'd');
2769
            },
2770
2771
            isoWeek : function (input) {
2772
                var week = weekOfYear(this, 1, 4).week;
2773
                return input == null ? week : this.add((input - week) * 7, 'd');
2774
            },
2775
2776
            weekday : function (input) {
2777
                var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
2778
                return input == null ? weekday : this.add(input - weekday, 'd');
2779
            },
2780
2781
            isoWeekday : function (input) {
2782
                // behaves the same as moment#day except
2783
                // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
2784
                // as a setter, sunday should belong to the previous week.
2785
                return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
2786
            },
2787
2788
            isoWeeksInYear : function () {
2789
                return weeksInYear(this.year(), 1, 4);
2790
            },
2791
2792
            weeksInYear : function () {
2793
                var weekInfo = this.localeData()._week;
2794
                return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
2795
            },
2796
2797
            get : function (units) {
2798
                units = normalizeUnits(units);
2799
                return this[units]();
2800
            },
2801
2802
            set : function (units, value) {
2803
                units = normalizeUnits(units);
2804
                if (typeof this[units] === 'function') {
2805
                    this[units](value);
2806
                }
2807
                return this;
2808
            },
2809
2810
            // If passed a locale key, it will set the locale for this
2811
            // instance.  Otherwise, it will return the locale configuration
2812
            // variables for this instance.
2813
            locale : function (key) {
2814
                var newLocaleData;
2815
2816
                if (key === undefined) {
2817
                    return this._locale._abbr;
2818
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2819
                    newLocaleData = moment.localeData(key);
2820
                    if (newLocaleData != null) {
2821
                        this._locale = newLocaleData;
2822
                    }
2823
                    return this;
2824
                }
2825
            },
2826
2827
            lang : deprecate(
2828
                'moment().lang() is deprecated. Use moment().localeData() instead.',
2829
                function (key) {
2830
                    if (key === undefined) {
2831
                        return this.localeData();
2832
                    } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2833
                        return this.locale(key);
2834
                    }
2835
                }
2836
            ),
2837
2838
            localeData : function () {
2839
                return this._locale;
2840
            },
2841
2842
            _dateTzOffset : function () {
2843
                // On Firefox.24 Date#getTimezoneOffset returns a floating point.
2844
                // https://github.com/moment/moment/pull/1871
2845
                return Math.round(this._d.getTimezoneOffset() / 15) * 15;
2846
            }
2847
        });
2848
2849
        function rawMonthSetter(mom, value) {
2850
            var dayOfMonth;
2851
2852
            // TODO: Move this out of here!
2853
            if (typeof value === 'string') {
2854
                value = mom.localeData().monthsParse(value);
2855
                // TODO: Another silent failure?
2856
                if (typeof value !== 'number') {
2857
                    return mom;
2858
                }
2859
            }
2860
2861
            dayOfMonth = Math.min(mom.date(),
2862
                    daysInMonth(mom.year(), value));
2863
            mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
2864
            return mom;
2865
        }
2866
2867
        function rawGetter(mom, unit) {
2868
            return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();
2869
        }
2870
2871
        function rawSetter(mom, unit, value) {
2872
            if (unit === 'Month') {
2873
                return rawMonthSetter(mom, value);
2874
            } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2875
                return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
2876
            }
2877
        }
2878
2879
        function makeAccessor(unit, keepTime) {
2880
            return function (value) {
2881
                if (value != null) {
2882
                    rawSetter(this, unit, value);
2883
                    moment.updateOffset(this, keepTime);
2884
                    return this;
2885
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
2886
                    return rawGetter(this, unit);
2887
                }
2888
            };
2889
        }
2890
2891
        moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false);
2892
        moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false);
2893
        moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false);
2894
        // Setting the hour should keep the time, because the user explicitly
2895
        // specified which hour he wants. So trying to maintain the same hour (in
2896
        // a new timezone) makes sense. Adding/subtracting hours does not follow
2897
        // this rule.
2898
        moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true);
2899
        // moment.fn.month is defined separately
2900
        moment.fn.date = makeAccessor('Date', true);
2901
        moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true));
2902
        moment.fn.year = makeAccessor('FullYear', true);
2903
        moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true));
2904
2905
        // add plural methods
2906
        moment.fn.days = moment.fn.day;
2907
        moment.fn.months = moment.fn.month;
2908
        moment.fn.weeks = moment.fn.week;
2909
        moment.fn.isoWeeks = moment.fn.isoWeek;
2910
        moment.fn.quarters = moment.fn.quarter;
2911
2912
        // add aliased format methods
2913
        moment.fn.toJSON = moment.fn.toISOString;
2914
2915
        /************************************
2916
            Duration Prototype
2917
        ************************************/
2918
2919
2920
        function daysToYears (days) {
2921
            // 400 years have 146097 days (taking into account leap year rules)
2922
            return days * 400 / 146097;
2923
        }
2924
2925
        function yearsToDays (years) {
2926
            // years * 365 + absRound(years / 4) -
2927
            //     absRound(years / 100) + absRound(years / 400);
2928
            return years * 146097 / 400;
2929
        }
2930
2931
        extend(moment.duration.fn = Duration.prototype, {
2932
2933
            _bubble : function () {
2934
                var milliseconds = this._milliseconds,
2935
                    days = this._days,
2936
                    months = this._months,
2937
                    data = this._data,
2938
                    seconds, minutes, hours, years = 0;
2939
2940
                // The following code bubbles up values, see the tests for
2941
                // examples of what that means.
2942
                data.milliseconds = milliseconds % 1000;
2943
2944
                seconds = absRound(milliseconds / 1000);
2945
                data.seconds = seconds % 60;
2946
2947
                minutes = absRound(seconds / 60);
2948
                data.minutes = minutes % 60;
2949
2950
                hours = absRound(minutes / 60);
2951
                data.hours = hours % 24;
2952
2953
                days += absRound(hours / 24);
2954
2955
                // Accurately convert days to years, assume start from year 0.
2956
                years = absRound(daysToYears(days));
2957
                days -= absRound(yearsToDays(years));
2958
2959
                // 30 days to a month
2960
                // TODO (iskren): Use anchor date (like 1st Jan) to compute this.
2961
                months += absRound(days / 30);
2962
                days %= 30;
2963
2964
                // 12 months -> 1 year
2965
                years += absRound(months / 12);
2966
                months %= 12;
2967
2968
                data.days = days;
2969
                data.months = months;
2970
                data.years = years;
2971
            },
2972
2973
            abs : function () {
2974
                this._milliseconds = Math.abs(this._milliseconds);
2975
                this._days = Math.abs(this._days);
2976
                this._months = Math.abs(this._months);
2977
2978
                this._data.milliseconds = Math.abs(this._data.milliseconds);
2979
                this._data.seconds = Math.abs(this._data.seconds);
2980
                this._data.minutes = Math.abs(this._data.minutes);
2981
                this._data.hours = Math.abs(this._data.hours);
2982
                this._data.months = Math.abs(this._data.months);
2983
                this._data.years = Math.abs(this._data.years);
2984
2985
                return this;
2986
            },
2987
2988
            weeks : function () {
2989
                return absRound(this.days() / 7);
2990
            },
2991
2992
            valueOf : function () {
2993
                return this._milliseconds +
2994
                  this._days * 864e5 +
2995
                  (this._months % 12) * 2592e6 +
2996
                  toInt(this._months / 12) * 31536e6;
2997
            },
2998
2999
            humanize : function (withSuffix) {
3000
                var output = relativeTime(this, !withSuffix, this.localeData());
3001
3002
                if (withSuffix) {
3003
                    output = this.localeData().pastFuture(+this, output);
3004
                }
3005
3006
                return this.localeData().postformat(output);
3007
            },
3008
3009
            add : function (input, val) {
3010
                // supports only 2.0-style add(1, 's') or add(moment)
3011
                var dur = moment.duration(input, val);
3012
3013
                this._milliseconds += dur._milliseconds;
3014
                this._days += dur._days;
3015
                this._months += dur._months;
3016
3017
                this._bubble();
3018
3019
                return this;
3020
            },
3021
3022
            subtract : function (input, val) {
3023
                var dur = moment.duration(input, val);
3024
3025
                this._milliseconds -= dur._milliseconds;
3026
                this._days -= dur._days;
3027
                this._months -= dur._months;
3028
3029
                this._bubble();
3030
3031
                return this;
3032
            },
3033
3034
            get : function (units) {
3035
                units = normalizeUnits(units);
3036
                return this[units.toLowerCase() + 's']();
3037
            },
3038
3039
            as : function (units) {
3040
                var days, months;
3041
                units = normalizeUnits(units);
3042
3043
                if (units === 'month' || units === 'year') {
3044
                    days = this._days + this._milliseconds / 864e5;
3045
                    months = this._months + daysToYears(days) * 12;
3046
                    return units === 'month' ? months : months / 12;
3047
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
3048
                    // handle milliseconds separately because of floating point math errors (issue #1867)
3049
                    days = this._days + yearsToDays(this._months / 12);
3050
                    switch (units) {
3051
                        case 'week': return days / 7 + this._milliseconds / 6048e5;
3052
                        case 'day': return days + this._milliseconds / 864e5;
3053
                        case 'hour': return days * 24 + this._milliseconds / 36e5;
3054
                        case 'minute': return days * 24 * 60 + this._milliseconds / 6e4;
3055
                        case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000;
3056
                        // Math.floor prevents floating point math errors here
3057
                        case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds;
3058
                        default: throw new Error('Unknown unit ' + units);
3059
                    }
3060
                }
3061
            },
3062
3063
            lang : moment.fn.lang,
3064
            locale : moment.fn.locale,
3065
3066
            toIsoString : deprecate(
3067
                'toIsoString() is deprecated. Please use toISOString() instead ' +
3068
                '(notice the capitals)',
3069
                function () {
3070
                    return this.toISOString();
3071
                }
3072
            ),
3073
3074
            toISOString : function () {
3075
                // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
3076
                var years = Math.abs(this.years()),
3077
                    months = Math.abs(this.months()),
3078
                    days = Math.abs(this.days()),
3079
                    hours = Math.abs(this.hours()),
3080
                    minutes = Math.abs(this.minutes()),
3081
                    seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
3082
3083
                if (!this.asSeconds()) {
3084
                    // this is the same as C#'s (Noda) and python (isodate)...
3085
                    // but not other JS (goog.date)
3086
                    return 'P0D';
3087
                }
3088
3089
                return (this.asSeconds() < 0 ? '-' : '') +
3090
                    'P' +
3091
                    (years ? years + 'Y' : '') +
3092
                    (months ? months + 'M' : '') +
3093
                    (days ? days + 'D' : '') +
3094
                    ((hours || minutes || seconds) ? 'T' : '') +
3095
                    (hours ? hours + 'H' : '') +
3096
                    (minutes ? minutes + 'M' : '') +
3097
                    (seconds ? seconds + 'S' : '');
3098
            },
3099
3100
            localeData : function () {
3101
                return this._locale;
3102
            }
3103
        });
3104
3105
        moment.duration.fn.toString = moment.duration.fn.toISOString;
3106
3107
        function makeDurationGetter(name) {
3108
            moment.duration.fn[name] = function () {
3109
                return this._data[name];
3110
            };
3111
        }
3112
3113
        for (i in unitMillisecondFactors) {
0 ignored issues
show
Complexity Coding Style introduced by
You seem to be assigning a new value to the loop variable i here. Please check if this was indeed your intention. Even if it was, consider using another kind of loop instead.
Loading history...
3114
            if (hasOwnProp(unitMillisecondFactors, i)) {
3115
                makeDurationGetter(i.toLowerCase());
3116
            }
3117
        }
3118
3119
        moment.duration.fn.asMilliseconds = function () {
3120
            return this.as('ms');
3121
        };
3122
        moment.duration.fn.asSeconds = function () {
3123
            return this.as('s');
3124
        };
3125
        moment.duration.fn.asMinutes = function () {
3126
            return this.as('m');
3127
        };
3128
        moment.duration.fn.asHours = function () {
3129
            return this.as('h');
3130
        };
3131
        moment.duration.fn.asDays = function () {
3132
            return this.as('d');
3133
        };
3134
        moment.duration.fn.asWeeks = function () {
3135
            return this.as('weeks');
3136
        };
3137
        moment.duration.fn.asMonths = function () {
3138
            return this.as('M');
3139
        };
3140
        moment.duration.fn.asYears = function () {
3141
            return this.as('y');
3142
        };
3143
3144
        /************************************
3145
            Default Locale
3146
        ************************************/
3147
3148
3149
        // Set default locale, other locale will inherit from English.
3150
        moment.locale('en', {
3151
            ordinal : function (number) {
3152
                var b = number % 10,
3153
                    output = (toInt(number % 100 / 10) === 1) ? 'th' :
3154
                    (b === 1) ? 'st' :
3155
                    (b === 2) ? 'nd' :
3156
                    (b === 3) ? 'rd' : 'th';
3157
                return number + output;
3158
            }
3159
        });
3160
3161
        return moment;
3162
3163
    }).call(this);
3164
3165
    UI.Utils.moment = moment;
3166
3167
    return UI.datepicker;
3168
});
3169