프로젝트

일반

사용자정보

통계
| 개정판:

root / HServer / 00.Server / 00.Program / node_modules / moment / moment.js

이력 | 보기 | 이력해설 | 다운로드 (129 KB)

1
//! moment.js
2

    
3
;(function (global, factory) {
4
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
5
    typeof define === 'function' && define.amd ? define(factory) :
6
    global.moment = factory()
7
}(this, (function () { 'use strict';
8

    
9
var hookCallback;
10

    
11
function hooks () {
12
    return hookCallback.apply(null, arguments);
13
}
14

    
15
// This is done to register the method called with moment()
16
// without creating circular dependencies.
17
function setHookCallback (callback) {
18
    hookCallback = callback;
19
}
20

    
21
function isArray(input) {
22
    return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
23
}
24

    
25
function isObject(input) {
26
    // IE8 will treat undefined and null as object if it wasn't for
27
    // input != null
28
    return input != null && Object.prototype.toString.call(input) === '[object Object]';
29
}
30

    
31
function isObjectEmpty(obj) {
32
    if (Object.getOwnPropertyNames) {
33
        return (Object.getOwnPropertyNames(obj).length === 0);
34
    } else {
35
        var k;
36
        for (k in obj) {
37
            if (obj.hasOwnProperty(k)) {
38
                return false;
39
            }
40
        }
41
        return true;
42
    }
43
}
44

    
45
function isUndefined(input) {
46
    return input === void 0;
47
}
48

    
49
function isNumber(input) {
50
    return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
51
}
52

    
53
function isDate(input) {
54
    return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
55
}
56

    
57
function map(arr, fn) {
58
    var res = [], i;
59
    for (i = 0; i < arr.length; ++i) {
60
        res.push(fn(arr[i], i));
61
    }
62
    return res;
63
}
64

    
65
function hasOwnProp(a, b) {
66
    return Object.prototype.hasOwnProperty.call(a, b);
67
}
68

    
69
function extend(a, b) {
70
    for (var i in b) {
71
        if (hasOwnProp(b, i)) {
72
            a[i] = b[i];
73
        }
74
    }
75

    
76
    if (hasOwnProp(b, 'toString')) {
77
        a.toString = b.toString;
78
    }
79

    
80
    if (hasOwnProp(b, 'valueOf')) {
81
        a.valueOf = b.valueOf;
82
    }
83

    
84
    return a;
85
}
86

    
87
function createUTC (input, format, locale, strict) {
88
    return createLocalOrUTC(input, format, locale, strict, true).utc();
89
}
90

    
91
function defaultParsingFlags() {
92
    // We need to deep clone this object.
93
    return {
94
        empty           : false,
95
        unusedTokens    : [],
96
        unusedInput     : [],
97
        overflow        : -2,
98
        charsLeftOver   : 0,
99
        nullInput       : false,
100
        invalidMonth    : null,
101
        invalidFormat   : false,
102
        userInvalidated : false,
103
        iso             : false,
104
        parsedDateParts : [],
105
        meridiem        : null,
106
        rfc2822         : false,
107
        weekdayMismatch : false
108
    };
109
}
110

    
111
function getParsingFlags(m) {
112
    if (m._pf == null) {
113
        m._pf = defaultParsingFlags();
114
    }
115
    return m._pf;
116
}
117

    
118
var some;
119
if (Array.prototype.some) {
120
    some = Array.prototype.some;
121
} else {
122
    some = function (fun) {
123
        var t = Object(this);
124
        var len = t.length >>> 0;
125

    
126
        for (var i = 0; i < len; i++) {
127
            if (i in t && fun.call(this, t[i], i, t)) {
128
                return true;
129
            }
130
        }
131

    
132
        return false;
133
    };
134
}
135

    
136
function isValid(m) {
137
    if (m._isValid == null) {
138
        var flags = getParsingFlags(m);
139
        var parsedParts = some.call(flags.parsedDateParts, function (i) {
140
            return i != null;
141
        });
142
        var isNowValid = !isNaN(m._d.getTime()) &&
143
            flags.overflow < 0 &&
144
            !flags.empty &&
145
            !flags.invalidMonth &&
146
            !flags.invalidWeekday &&
147
            !flags.weekdayMismatch &&
148
            !flags.nullInput &&
149
            !flags.invalidFormat &&
150
            !flags.userInvalidated &&
151
            (!flags.meridiem || (flags.meridiem && parsedParts));
152

    
153
        if (m._strict) {
154
            isNowValid = isNowValid &&
155
                flags.charsLeftOver === 0 &&
156
                flags.unusedTokens.length === 0 &&
157
                flags.bigHour === undefined;
158
        }
159

    
160
        if (Object.isFrozen == null || !Object.isFrozen(m)) {
161
            m._isValid = isNowValid;
162
        }
163
        else {
164
            return isNowValid;
165
        }
166
    }
167
    return m._isValid;
168
}
169

    
170
function createInvalid (flags) {
171
    var m = createUTC(NaN);
172
    if (flags != null) {
173
        extend(getParsingFlags(m), flags);
174
    }
175
    else {
176
        getParsingFlags(m).userInvalidated = true;
177
    }
178

    
179
    return m;
180
}
181

    
182
// Plugins that add properties should also add the key here (null value),
183
// so we can properly clone ourselves.
184
var momentProperties = hooks.momentProperties = [];
185

    
186
function copyConfig(to, from) {
187
    var i, prop, val;
188

    
189
    if (!isUndefined(from._isAMomentObject)) {
190
        to._isAMomentObject = from._isAMomentObject;
191
    }
192
    if (!isUndefined(from._i)) {
193
        to._i = from._i;
194
    }
195
    if (!isUndefined(from._f)) {
196
        to._f = from._f;
197
    }
198
    if (!isUndefined(from._l)) {
199
        to._l = from._l;
200
    }
201
    if (!isUndefined(from._strict)) {
202
        to._strict = from._strict;
203
    }
204
    if (!isUndefined(from._tzm)) {
205
        to._tzm = from._tzm;
206
    }
207
    if (!isUndefined(from._isUTC)) {
208
        to._isUTC = from._isUTC;
209
    }
210
    if (!isUndefined(from._offset)) {
211
        to._offset = from._offset;
212
    }
213
    if (!isUndefined(from._pf)) {
214
        to._pf = getParsingFlags(from);
215
    }
216
    if (!isUndefined(from._locale)) {
217
        to._locale = from._locale;
218
    }
219

    
220
    if (momentProperties.length > 0) {
221
        for (i = 0; i < momentProperties.length; i++) {
222
            prop = momentProperties[i];
223
            val = from[prop];
224
            if (!isUndefined(val)) {
225
                to[prop] = val;
226
            }
227
        }
228
    }
229

    
230
    return to;
231
}
232

    
233
var updateInProgress = false;
234

    
235
// Moment prototype object
236
function Moment(config) {
237
    copyConfig(this, config);
238
    this._d = new Date(config._d != null ? config._d.getTime() : NaN);
239
    if (!this.isValid()) {
240
        this._d = new Date(NaN);
241
    }
242
    // Prevent infinite loop in case updateOffset creates new moment
243
    // objects.
244
    if (updateInProgress === false) {
245
        updateInProgress = true;
246
        hooks.updateOffset(this);
247
        updateInProgress = false;
248
    }
249
}
250

    
251
function isMoment (obj) {
252
    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
253
}
254

    
255
function absFloor (number) {
256
    if (number < 0) {
257
        // -0 -> 0
258
        return Math.ceil(number) || 0;
259
    } else {
260
        return Math.floor(number);
261
    }
262
}
263

    
264
function toInt(argumentForCoercion) {
265
    var coercedNumber = +argumentForCoercion,
266
        value = 0;
267

    
268
    if (coercedNumber !== 0 && isFinite(coercedNumber)) {
269
        value = absFloor(coercedNumber);
270
    }
271

    
272
    return value;
273
}
274

    
275
// compare two arrays, return the number of differences
276
function compareArrays(array1, array2, dontConvert) {
277
    var len = Math.min(array1.length, array2.length),
278
        lengthDiff = Math.abs(array1.length - array2.length),
279
        diffs = 0,
280
        i;
281
    for (i = 0; i < len; i++) {
282
        if ((dontConvert && array1[i] !== array2[i]) ||
283
            (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
284
            diffs++;
285
        }
286
    }
287
    return diffs + lengthDiff;
288
}
289

    
290
function warn(msg) {
291
    if (hooks.suppressDeprecationWarnings === false &&
292
            (typeof console !==  'undefined') && console.warn) {
293
        console.warn('Deprecation warning: ' + msg);
294
    }
295
}
296

    
297
function deprecate(msg, fn) {
298
    var firstTime = true;
299

    
300
    return extend(function () {
301
        if (hooks.deprecationHandler != null) {
302
            hooks.deprecationHandler(null, msg);
303
        }
304
        if (firstTime) {
305
            var args = [];
306
            var arg;
307
            for (var i = 0; i < arguments.length; i++) {
308
                arg = '';
309
                if (typeof arguments[i] === 'object') {
310
                    arg += '\n[' + i + '] ';
311
                    for (var key in arguments[0]) {
312
                        arg += key + ': ' + arguments[0][key] + ', ';
313
                    }
314
                    arg = arg.slice(0, -2); // Remove trailing comma and space
315
                } else {
316
                    arg = arguments[i];
317
                }
318
                args.push(arg);
319
            }
320
            warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
321
            firstTime = false;
322
        }
323
        return fn.apply(this, arguments);
324
    }, fn);
325
}
326

    
327
var deprecations = {};
328

    
329
function deprecateSimple(name, msg) {
330
    if (hooks.deprecationHandler != null) {
331
        hooks.deprecationHandler(name, msg);
332
    }
333
    if (!deprecations[name]) {
334
        warn(msg);
335
        deprecations[name] = true;
336
    }
337
}
338

    
339
hooks.suppressDeprecationWarnings = false;
340
hooks.deprecationHandler = null;
341

    
342
function isFunction(input) {
343
    return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
344
}
345

    
346
function set (config) {
347
    var prop, i;
348
    for (i in config) {
349
        prop = config[i];
350
        if (isFunction(prop)) {
351
            this[i] = prop;
352
        } else {
353
            this['_' + i] = prop;
354
        }
355
    }
356
    this._config = config;
357
    // Lenient ordinal parsing accepts just a number in addition to
358
    // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
359
    // TODO: Remove "ordinalParse" fallback in next major release.
360
    this._dayOfMonthOrdinalParseLenient = new RegExp(
361
        (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
362
            '|' + (/\d{1,2}/).source);
363
}
364

    
365
function mergeConfigs(parentConfig, childConfig) {
366
    var res = extend({}, parentConfig), prop;
367
    for (prop in childConfig) {
368
        if (hasOwnProp(childConfig, prop)) {
369
            if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
370
                res[prop] = {};
371
                extend(res[prop], parentConfig[prop]);
372
                extend(res[prop], childConfig[prop]);
373
            } else if (childConfig[prop] != null) {
374
                res[prop] = childConfig[prop];
375
            } else {
376
                delete res[prop];
377
            }
378
        }
379
    }
380
    for (prop in parentConfig) {
381
        if (hasOwnProp(parentConfig, prop) &&
382
                !hasOwnProp(childConfig, prop) &&
383
                isObject(parentConfig[prop])) {
384
            // make sure changes to properties don't modify parent config
385
            res[prop] = extend({}, res[prop]);
386
        }
387
    }
388
    return res;
389
}
390

    
391
function Locale(config) {
392
    if (config != null) {
393
        this.set(config);
394
    }
395
}
396

    
397
var keys;
398

    
399
if (Object.keys) {
400
    keys = Object.keys;
401
} else {
402
    keys = function (obj) {
403
        var i, res = [];
404
        for (i in obj) {
405
            if (hasOwnProp(obj, i)) {
406
                res.push(i);
407
            }
408
        }
409
        return res;
410
    };
411
}
412

    
413
var defaultCalendar = {
414
    sameDay : '[Today at] LT',
415
    nextDay : '[Tomorrow at] LT',
416
    nextWeek : 'dddd [at] LT',
417
    lastDay : '[Yesterday at] LT',
418
    lastWeek : '[Last] dddd [at] LT',
419
    sameElse : 'L'
420
};
421

    
422
function calendar (key, mom, now) {
423
    var output = this._calendar[key] || this._calendar['sameElse'];
424
    return isFunction(output) ? output.call(mom, now) : output;
425
}
426

    
427
var defaultLongDateFormat = {
428
    LTS  : 'h:mm:ss A',
429
    LT   : 'h:mm A',
430
    L    : 'MM/DD/YYYY',
431
    LL   : 'MMMM D, YYYY',
432
    LLL  : 'MMMM D, YYYY h:mm A',
433
    LLLL : 'dddd, MMMM D, YYYY h:mm A'
434
};
435

    
436
function longDateFormat (key) {
437
    var format = this._longDateFormat[key],
438
        formatUpper = this._longDateFormat[key.toUpperCase()];
439

    
440
    if (format || !formatUpper) {
441
        return format;
442
    }
443

    
444
    this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
445
        return val.slice(1);
446
    });
447

    
448
    return this._longDateFormat[key];
449
}
450

    
451
var defaultInvalidDate = 'Invalid date';
452

    
453
function invalidDate () {
454
    return this._invalidDate;
455
}
456

    
457
var defaultOrdinal = '%d';
458
var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
459

    
460
function ordinal (number) {
461
    return this._ordinal.replace('%d', number);
462
}
463

    
464
var defaultRelativeTime = {
465
    future : 'in %s',
466
    past   : '%s ago',
467
    s  : 'a few seconds',
468
    ss : '%d seconds',
469
    m  : 'a minute',
470
    mm : '%d minutes',
471
    h  : 'an hour',
472
    hh : '%d hours',
473
    d  : 'a day',
474
    dd : '%d days',
475
    M  : 'a month',
476
    MM : '%d months',
477
    y  : 'a year',
478
    yy : '%d years'
479
};
480

    
481
function relativeTime (number, withoutSuffix, string, isFuture) {
482
    var output = this._relativeTime[string];
483
    return (isFunction(output)) ?
484
        output(number, withoutSuffix, string, isFuture) :
485
        output.replace(/%d/i, number);
486
}
487

    
488
function pastFuture (diff, output) {
489
    var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
490
    return isFunction(format) ? format(output) : format.replace(/%s/i, output);
491
}
492

    
493
var aliases = {};
494

    
495
function addUnitAlias (unit, shorthand) {
496
    var lowerCase = unit.toLowerCase();
497
    aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
498
}
499

    
500
function normalizeUnits(units) {
501
    return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
502
}
503

    
504
function normalizeObjectUnits(inputObject) {
505
    var normalizedInput = {},
506
        normalizedProp,
507
        prop;
508

    
509
    for (prop in inputObject) {
510
        if (hasOwnProp(inputObject, prop)) {
511
            normalizedProp = normalizeUnits(prop);
512
            if (normalizedProp) {
513
                normalizedInput[normalizedProp] = inputObject[prop];
514
            }
515
        }
516
    }
517

    
518
    return normalizedInput;
519
}
520

    
521
var priorities = {};
522

    
523
function addUnitPriority(unit, priority) {
524
    priorities[unit] = priority;
525
}
526

    
527
function getPrioritizedUnits(unitsObj) {
528
    var units = [];
529
    for (var u in unitsObj) {
530
        units.push({unit: u, priority: priorities[u]});
531
    }
532
    units.sort(function (a, b) {
533
        return a.priority - b.priority;
534
    });
535
    return units;
536
}
537

    
538
function zeroFill(number, targetLength, forceSign) {
539
    var absNumber = '' + Math.abs(number),
540
        zerosToFill = targetLength - absNumber.length,
541
        sign = number >= 0;
542
    return (sign ? (forceSign ? '+' : '') : '-') +
543
        Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
544
}
545

    
546
var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
547

    
548
var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
549

    
550
var formatFunctions = {};
551

    
552
var formatTokenFunctions = {};
553

    
554
// token:    'M'
555
// padded:   ['MM', 2]
556
// ordinal:  'Mo'
557
// callback: function () { this.month() + 1 }
558
function addFormatToken (token, padded, ordinal, callback) {
559
    var func = callback;
560
    if (typeof callback === 'string') {
561
        func = function () {
562
            return this[callback]();
563
        };
564
    }
565
    if (token) {
566
        formatTokenFunctions[token] = func;
567
    }
568
    if (padded) {
569
        formatTokenFunctions[padded[0]] = function () {
570
            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
571
        };
572
    }
573
    if (ordinal) {
574
        formatTokenFunctions[ordinal] = function () {
575
            return this.localeData().ordinal(func.apply(this, arguments), token);
576
        };
577
    }
578
}
579

    
580
function removeFormattingTokens(input) {
581
    if (input.match(/\[[\s\S]/)) {
582
        return input.replace(/^\[|\]$/g, '');
583
    }
584
    return input.replace(/\\/g, '');
585
}
586

    
587
function makeFormatFunction(format) {
588
    var array = format.match(formattingTokens), i, length;
589

    
590
    for (i = 0, length = array.length; i < length; i++) {
591
        if (formatTokenFunctions[array[i]]) {
592
            array[i] = formatTokenFunctions[array[i]];
593
        } else {
594
            array[i] = removeFormattingTokens(array[i]);
595
        }
596
    }
597

    
598
    return function (mom) {
599
        var output = '', i;
600
        for (i = 0; i < length; i++) {
601
            output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
602
        }
603
        return output;
604
    };
605
}
606

    
607
// format date using native date object
608
function formatMoment(m, format) {
609
    if (!m.isValid()) {
610
        return m.localeData().invalidDate();
611
    }
612

    
613
    format = expandFormat(format, m.localeData());
614
    formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
615

    
616
    return formatFunctions[format](m);
617
}
618

    
619
function expandFormat(format, locale) {
620
    var i = 5;
621

    
622
    function replaceLongDateFormatTokens(input) {
623
        return locale.longDateFormat(input) || input;
624
    }
625

    
626
    localFormattingTokens.lastIndex = 0;
627
    while (i >= 0 && localFormattingTokens.test(format)) {
628
        format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
629
        localFormattingTokens.lastIndex = 0;
630
        i -= 1;
631
    }
632

    
633
    return format;
634
}
635

    
636
var match1         = /\d/;            //       0 - 9
637
var match2         = /\d\d/;          //      00 - 99
638
var match3         = /\d{3}/;         //     000 - 999
639
var match4         = /\d{4}/;         //    0000 - 9999
640
var match6         = /[+-]?\d{6}/;    // -999999 - 999999
641
var match1to2      = /\d\d?/;         //       0 - 99
642
var match3to4      = /\d\d\d\d?/;     //     999 - 9999
643
var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
644
var match1to3      = /\d{1,3}/;       //       0 - 999
645
var match1to4      = /\d{1,4}/;       //       0 - 9999
646
var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
647

    
648
var matchUnsigned  = /\d+/;           //       0 - inf
649
var matchSigned    = /[+-]?\d+/;      //    -inf - inf
650

    
651
var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
652
var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
653

    
654
var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
655

    
656
// any word (or two) characters or numbers including two/three word month in arabic.
657
// includes scottish gaelic two word and hyphenated months
658
var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
659

    
660
var regexes = {};
661

    
662
function addRegexToken (token, regex, strictRegex) {
663
    regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
664
        return (isStrict && strictRegex) ? strictRegex : regex;
665
    };
666
}
667

    
668
function getParseRegexForToken (token, config) {
669
    if (!hasOwnProp(regexes, token)) {
670
        return new RegExp(unescapeFormat(token));
671
    }
672

    
673
    return regexes[token](config._strict, config._locale);
674
}
675

    
676
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
677
function unescapeFormat(s) {
678
    return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
679
        return p1 || p2 || p3 || p4;
680
    }));
681
}
682

    
683
function regexEscape(s) {
684
    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
685
}
686

    
687
var tokens = {};
688

    
689
function addParseToken (token, callback) {
690
    var i, func = callback;
691
    if (typeof token === 'string') {
692
        token = [token];
693
    }
694
    if (isNumber(callback)) {
695
        func = function (input, array) {
696
            array[callback] = toInt(input);
697
        };
698
    }
699
    for (i = 0; i < token.length; i++) {
700
        tokens[token[i]] = func;
701
    }
702
}
703

    
704
function addWeekParseToken (token, callback) {
705
    addParseToken(token, function (input, array, config, token) {
706
        config._w = config._w || {};
707
        callback(input, config._w, config, token);
708
    });
709
}
710

    
711
function addTimeToArrayFromToken(token, input, config) {
712
    if (input != null && hasOwnProp(tokens, token)) {
713
        tokens[token](input, config._a, config, token);
714
    }
715
}
716

    
717
var YEAR = 0;
718
var MONTH = 1;
719
var DATE = 2;
720
var HOUR = 3;
721
var MINUTE = 4;
722
var SECOND = 5;
723
var MILLISECOND = 6;
724
var WEEK = 7;
725
var WEEKDAY = 8;
726

    
727
// FORMATTING
728

    
729
addFormatToken('Y', 0, 0, function () {
730
    var y = this.year();
731
    return y <= 9999 ? '' + y : '+' + y;
732
});
733

    
734
addFormatToken(0, ['YY', 2], 0, function () {
735
    return this.year() % 100;
736
});
737

    
738
addFormatToken(0, ['YYYY',   4],       0, 'year');
739
addFormatToken(0, ['YYYYY',  5],       0, 'year');
740
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
741

    
742
// ALIASES
743

    
744
addUnitAlias('year', 'y');
745

    
746
// PRIORITIES
747

    
748
addUnitPriority('year', 1);
749

    
750
// PARSING
751

    
752
addRegexToken('Y',      matchSigned);
753
addRegexToken('YY',     match1to2, match2);
754
addRegexToken('YYYY',   match1to4, match4);
755
addRegexToken('YYYYY',  match1to6, match6);
756
addRegexToken('YYYYYY', match1to6, match6);
757

    
758
addParseToken(['YYYYY', 'YYYYYY'], YEAR);
759
addParseToken('YYYY', function (input, array) {
760
    array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
761
});
762
addParseToken('YY', function (input, array) {
763
    array[YEAR] = hooks.parseTwoDigitYear(input);
764
});
765
addParseToken('Y', function (input, array) {
766
    array[YEAR] = parseInt(input, 10);
767
});
768

    
769
// HELPERS
770

    
771
function daysInYear(year) {
772
    return isLeapYear(year) ? 366 : 365;
773
}
774

    
775
function isLeapYear(year) {
776
    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
777
}
778

    
779
// HOOKS
780

    
781
hooks.parseTwoDigitYear = function (input) {
782
    return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
783
};
784

    
785
// MOMENTS
786

    
787
var getSetYear = makeGetSet('FullYear', true);
788

    
789
function getIsLeapYear () {
790
    return isLeapYear(this.year());
791
}
792

    
793
function makeGetSet (unit, keepTime) {
794
    return function (value) {
795
        if (value != null) {
796
            set$1(this, unit, value);
797
            hooks.updateOffset(this, keepTime);
798
            return this;
799
        } else {
800
            return get(this, unit);
801
        }
802
    };
803
}
804

    
805
function get (mom, unit) {
806
    return mom.isValid() ?
807
        mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
808
}
809

    
810
function set$1 (mom, unit, value) {
811
    if (mom.isValid() && !isNaN(value)) {
812
        if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
813
            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
814
        }
815
        else {
816
            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
817
        }
818
    }
819
}
820

    
821
// MOMENTS
822

    
823
function stringGet (units) {
824
    units = normalizeUnits(units);
825
    if (isFunction(this[units])) {
826
        return this[units]();
827
    }
828
    return this;
829
}
830

    
831

    
832
function stringSet (units, value) {
833
    if (typeof units === 'object') {
834
        units = normalizeObjectUnits(units);
835
        var prioritized = getPrioritizedUnits(units);
836
        for (var i = 0; i < prioritized.length; i++) {
837
            this[prioritized[i].unit](units[prioritized[i].unit]);
838
        }
839
    } else {
840
        units = normalizeUnits(units);
841
        if (isFunction(this[units])) {
842
            return this[units](value);
843
        }
844
    }
845
    return this;
846
}
847

    
848
function mod(n, x) {
849
    return ((n % x) + x) % x;
850
}
851

    
852
var indexOf;
853

    
854
if (Array.prototype.indexOf) {
855
    indexOf = Array.prototype.indexOf;
856
} else {
857
    indexOf = function (o) {
858
        // I know
859
        var i;
860
        for (i = 0; i < this.length; ++i) {
861
            if (this[i] === o) {
862
                return i;
863
            }
864
        }
865
        return -1;
866
    };
867
}
868

    
869
function daysInMonth(year, month) {
870
    if (isNaN(year) || isNaN(month)) {
871
        return NaN;
872
    }
873
    var modMonth = mod(month, 12);
874
    year += (month - modMonth) / 12;
875
    return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
876
}
877

    
878
// FORMATTING
879

    
880
addFormatToken('M', ['MM', 2], 'Mo', function () {
881
    return this.month() + 1;
882
});
883

    
884
addFormatToken('MMM', 0, 0, function (format) {
885
    return this.localeData().monthsShort(this, format);
886
});
887

    
888
addFormatToken('MMMM', 0, 0, function (format) {
889
    return this.localeData().months(this, format);
890
});
891

    
892
// ALIASES
893

    
894
addUnitAlias('month', 'M');
895

    
896
// PRIORITY
897

    
898
addUnitPriority('month', 8);
899

    
900
// PARSING
901

    
902
addRegexToken('M',    match1to2);
903
addRegexToken('MM',   match1to2, match2);
904
addRegexToken('MMM',  function (isStrict, locale) {
905
    return locale.monthsShortRegex(isStrict);
906
});
907
addRegexToken('MMMM', function (isStrict, locale) {
908
    return locale.monthsRegex(isStrict);
909
});
910

    
911
addParseToken(['M', 'MM'], function (input, array) {
912
    array[MONTH] = toInt(input) - 1;
913
});
914

    
915
addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
916
    var month = config._locale.monthsParse(input, token, config._strict);
917
    // if we didn't find a month name, mark the date as invalid.
918
    if (month != null) {
919
        array[MONTH] = month;
920
    } else {
921
        getParsingFlags(config).invalidMonth = input;
922
    }
923
});
924

    
925
// LOCALES
926

    
927
var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
928
var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
929
function localeMonths (m, format) {
930
    if (!m) {
931
        return isArray(this._months) ? this._months :
932
            this._months['standalone'];
933
    }
934
    return isArray(this._months) ? this._months[m.month()] :
935
        this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
936
}
937

    
938
var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
939
function localeMonthsShort (m, format) {
940
    if (!m) {
941
        return isArray(this._monthsShort) ? this._monthsShort :
942
            this._monthsShort['standalone'];
943
    }
944
    return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
945
        this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
946
}
947

    
948
function handleStrictParse(monthName, format, strict) {
949
    var i, ii, mom, llc = monthName.toLocaleLowerCase();
950
    if (!this._monthsParse) {
951
        // this is not used
952
        this._monthsParse = [];
953
        this._longMonthsParse = [];
954
        this._shortMonthsParse = [];
955
        for (i = 0; i < 12; ++i) {
956
            mom = createUTC([2000, i]);
957
            this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
958
            this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
959
        }
960
    }
961

    
962
    if (strict) {
963
        if (format === 'MMM') {
964
            ii = indexOf.call(this._shortMonthsParse, llc);
965
            return ii !== -1 ? ii : null;
966
        } else {
967
            ii = indexOf.call(this._longMonthsParse, llc);
968
            return ii !== -1 ? ii : null;
969
        }
970
    } else {
971
        if (format === 'MMM') {
972
            ii = indexOf.call(this._shortMonthsParse, llc);
973
            if (ii !== -1) {
974
                return ii;
975
            }
976
            ii = indexOf.call(this._longMonthsParse, llc);
977
            return ii !== -1 ? ii : null;
978
        } else {
979
            ii = indexOf.call(this._longMonthsParse, llc);
980
            if (ii !== -1) {
981
                return ii;
982
            }
983
            ii = indexOf.call(this._shortMonthsParse, llc);
984
            return ii !== -1 ? ii : null;
985
        }
986
    }
987
}
988

    
989
function localeMonthsParse (monthName, format, strict) {
990
    var i, mom, regex;
991

    
992
    if (this._monthsParseExact) {
993
        return handleStrictParse.call(this, monthName, format, strict);
994
    }
995

    
996
    if (!this._monthsParse) {
997
        this._monthsParse = [];
998
        this._longMonthsParse = [];
999
        this._shortMonthsParse = [];
1000
    }
1001

    
1002
    // TODO: add sorting
1003
    // Sorting makes sure if one month (or abbr) is a prefix of another
1004
    // see sorting in computeMonthsParse
1005
    for (i = 0; i < 12; i++) {
1006
        // make the regex if we don't have it already
1007
        mom = createUTC([2000, i]);
1008
        if (strict && !this._longMonthsParse[i]) {
1009
            this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
1010
            this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
1011
        }
1012
        if (!strict && !this._monthsParse[i]) {
1013
            regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
1014
            this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
1015
        }
1016
        // test the regex
1017
        if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
1018
            return i;
1019
        } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
1020
            return i;
1021
        } else if (!strict && this._monthsParse[i].test(monthName)) {
1022
            return i;
1023
        }
1024
    }
1025
}
1026

    
1027
// MOMENTS
1028

    
1029
function setMonth (mom, value) {
1030
    var dayOfMonth;
1031

    
1032
    if (!mom.isValid()) {
1033
        // No op
1034
        return mom;
1035
    }
1036

    
1037
    if (typeof value === 'string') {
1038
        if (/^\d+$/.test(value)) {
1039
            value = toInt(value);
1040
        } else {
1041
            value = mom.localeData().monthsParse(value);
1042
            // TODO: Another silent failure?
1043
            if (!isNumber(value)) {
1044
                return mom;
1045
            }
1046
        }
1047
    }
1048

    
1049
    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
1050
    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
1051
    return mom;
1052
}
1053

    
1054
function getSetMonth (value) {
1055
    if (value != null) {
1056
        setMonth(this, value);
1057
        hooks.updateOffset(this, true);
1058
        return this;
1059
    } else {
1060
        return get(this, 'Month');
1061
    }
1062
}
1063

    
1064
function getDaysInMonth () {
1065
    return daysInMonth(this.year(), this.month());
1066
}
1067

    
1068
var defaultMonthsShortRegex = matchWord;
1069
function monthsShortRegex (isStrict) {
1070
    if (this._monthsParseExact) {
1071
        if (!hasOwnProp(this, '_monthsRegex')) {
1072
            computeMonthsParse.call(this);
1073
        }
1074
        if (isStrict) {
1075
            return this._monthsShortStrictRegex;
1076
        } else {
1077
            return this._monthsShortRegex;
1078
        }
1079
    } else {
1080
        if (!hasOwnProp(this, '_monthsShortRegex')) {
1081
            this._monthsShortRegex = defaultMonthsShortRegex;
1082
        }
1083
        return this._monthsShortStrictRegex && isStrict ?
1084
            this._monthsShortStrictRegex : this._monthsShortRegex;
1085
    }
1086
}
1087

    
1088
var defaultMonthsRegex = matchWord;
1089
function monthsRegex (isStrict) {
1090
    if (this._monthsParseExact) {
1091
        if (!hasOwnProp(this, '_monthsRegex')) {
1092
            computeMonthsParse.call(this);
1093
        }
1094
        if (isStrict) {
1095
            return this._monthsStrictRegex;
1096
        } else {
1097
            return this._monthsRegex;
1098
        }
1099
    } else {
1100
        if (!hasOwnProp(this, '_monthsRegex')) {
1101
            this._monthsRegex = defaultMonthsRegex;
1102
        }
1103
        return this._monthsStrictRegex && isStrict ?
1104
            this._monthsStrictRegex : this._monthsRegex;
1105
    }
1106
}
1107

    
1108
function computeMonthsParse () {
1109
    function cmpLenRev(a, b) {
1110
        return b.length - a.length;
1111
    }
1112

    
1113
    var shortPieces = [], longPieces = [], mixedPieces = [],
1114
        i, mom;
1115
    for (i = 0; i < 12; i++) {
1116
        // make the regex if we don't have it already
1117
        mom = createUTC([2000, i]);
1118
        shortPieces.push(this.monthsShort(mom, ''));
1119
        longPieces.push(this.months(mom, ''));
1120
        mixedPieces.push(this.months(mom, ''));
1121
        mixedPieces.push(this.monthsShort(mom, ''));
1122
    }
1123
    // Sorting makes sure if one month (or abbr) is a prefix of another it
1124
    // will match the longer piece.
1125
    shortPieces.sort(cmpLenRev);
1126
    longPieces.sort(cmpLenRev);
1127
    mixedPieces.sort(cmpLenRev);
1128
    for (i = 0; i < 12; i++) {
1129
        shortPieces[i] = regexEscape(shortPieces[i]);
1130
        longPieces[i] = regexEscape(longPieces[i]);
1131
    }
1132
    for (i = 0; i < 24; i++) {
1133
        mixedPieces[i] = regexEscape(mixedPieces[i]);
1134
    }
1135

    
1136
    this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1137
    this._monthsShortRegex = this._monthsRegex;
1138
    this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1139
    this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
1140
}
1141

    
1142
function createDate (y, m, d, h, M, s, ms) {
1143
    // can't just apply() to create a date:
1144
    // https://stackoverflow.com/q/181348
1145
    var date = new Date(y, m, d, h, M, s, ms);
1146

    
1147
    // the date constructor remaps years 0-99 to 1900-1999
1148
    if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
1149
        date.setFullYear(y);
1150
    }
1151
    return date;
1152
}
1153

    
1154
function createUTCDate (y) {
1155
    var date = new Date(Date.UTC.apply(null, arguments));
1156

    
1157
    // the Date.UTC function remaps years 0-99 to 1900-1999
1158
    if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
1159
        date.setUTCFullYear(y);
1160
    }
1161
    return date;
1162
}
1163

    
1164
// start-of-first-week - start-of-year
1165
function firstWeekOffset(year, dow, doy) {
1166
    var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
1167
        fwd = 7 + dow - doy,
1168
        // first-week day local weekday -- which local weekday is fwd
1169
        fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
1170

    
1171
    return -fwdlw + fwd - 1;
1172
}
1173

    
1174
// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1175
function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
1176
    var localWeekday = (7 + weekday - dow) % 7,
1177
        weekOffset = firstWeekOffset(year, dow, doy),
1178
        dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
1179
        resYear, resDayOfYear;
1180

    
1181
    if (dayOfYear <= 0) {
1182
        resYear = year - 1;
1183
        resDayOfYear = daysInYear(resYear) + dayOfYear;
1184
    } else if (dayOfYear > daysInYear(year)) {
1185
        resYear = year + 1;
1186
        resDayOfYear = dayOfYear - daysInYear(year);
1187
    } else {
1188
        resYear = year;
1189
        resDayOfYear = dayOfYear;
1190
    }
1191

    
1192
    return {
1193
        year: resYear,
1194
        dayOfYear: resDayOfYear
1195
    };
1196
}
1197

    
1198
function weekOfYear(mom, dow, doy) {
1199
    var weekOffset = firstWeekOffset(mom.year(), dow, doy),
1200
        week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
1201
        resWeek, resYear;
1202

    
1203
    if (week < 1) {
1204
        resYear = mom.year() - 1;
1205
        resWeek = week + weeksInYear(resYear, dow, doy);
1206
    } else if (week > weeksInYear(mom.year(), dow, doy)) {
1207
        resWeek = week - weeksInYear(mom.year(), dow, doy);
1208
        resYear = mom.year() + 1;
1209
    } else {
1210
        resYear = mom.year();
1211
        resWeek = week;
1212
    }
1213

    
1214
    return {
1215
        week: resWeek,
1216
        year: resYear
1217
    };
1218
}
1219

    
1220
function weeksInYear(year, dow, doy) {
1221
    var weekOffset = firstWeekOffset(year, dow, doy),
1222
        weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
1223
    return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
1224
}
1225

    
1226
// FORMATTING
1227

    
1228
addFormatToken('w', ['ww', 2], 'wo', 'week');
1229
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
1230

    
1231
// ALIASES
1232

    
1233
addUnitAlias('week', 'w');
1234
addUnitAlias('isoWeek', 'W');
1235

    
1236
// PRIORITIES
1237

    
1238
addUnitPriority('week', 5);
1239
addUnitPriority('isoWeek', 5);
1240

    
1241
// PARSING
1242

    
1243
addRegexToken('w',  match1to2);
1244
addRegexToken('ww', match1to2, match2);
1245
addRegexToken('W',  match1to2);
1246
addRegexToken('WW', match1to2, match2);
1247

    
1248
addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
1249
    week[token.substr(0, 1)] = toInt(input);
1250
});
1251

    
1252
// HELPERS
1253

    
1254
// LOCALES
1255

    
1256
function localeWeek (mom) {
1257
    return weekOfYear(mom, this._week.dow, this._week.doy).week;
1258
}
1259

    
1260
var defaultLocaleWeek = {
1261
    dow : 0, // Sunday is the first day of the week.
1262
    doy : 6  // The week that contains Jan 1st is the first week of the year.
1263
};
1264

    
1265
function localeFirstDayOfWeek () {
1266
    return this._week.dow;
1267
}
1268

    
1269
function localeFirstDayOfYear () {
1270
    return this._week.doy;
1271
}
1272

    
1273
// MOMENTS
1274

    
1275
function getSetWeek (input) {
1276
    var week = this.localeData().week(this);
1277
    return input == null ? week : this.add((input - week) * 7, 'd');
1278
}
1279

    
1280
function getSetISOWeek (input) {
1281
    var week = weekOfYear(this, 1, 4).week;
1282
    return input == null ? week : this.add((input - week) * 7, 'd');
1283
}
1284

    
1285
// FORMATTING
1286

    
1287
addFormatToken('d', 0, 'do', 'day');
1288

    
1289
addFormatToken('dd', 0, 0, function (format) {
1290
    return this.localeData().weekdaysMin(this, format);
1291
});
1292

    
1293
addFormatToken('ddd', 0, 0, function (format) {
1294
    return this.localeData().weekdaysShort(this, format);
1295
});
1296

    
1297
addFormatToken('dddd', 0, 0, function (format) {
1298
    return this.localeData().weekdays(this, format);
1299
});
1300

    
1301
addFormatToken('e', 0, 0, 'weekday');
1302
addFormatToken('E', 0, 0, 'isoWeekday');
1303

    
1304
// ALIASES
1305

    
1306
addUnitAlias('day', 'd');
1307
addUnitAlias('weekday', 'e');
1308
addUnitAlias('isoWeekday', 'E');
1309

    
1310
// PRIORITY
1311
addUnitPriority('day', 11);
1312
addUnitPriority('weekday', 11);
1313
addUnitPriority('isoWeekday', 11);
1314

    
1315
// PARSING
1316

    
1317
addRegexToken('d',    match1to2);
1318
addRegexToken('e',    match1to2);
1319
addRegexToken('E',    match1to2);
1320
addRegexToken('dd',   function (isStrict, locale) {
1321
    return locale.weekdaysMinRegex(isStrict);
1322
});
1323
addRegexToken('ddd',   function (isStrict, locale) {
1324
    return locale.weekdaysShortRegex(isStrict);
1325
});
1326
addRegexToken('dddd',   function (isStrict, locale) {
1327
    return locale.weekdaysRegex(isStrict);
1328
});
1329

    
1330
addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
1331
    var weekday = config._locale.weekdaysParse(input, token, config._strict);
1332
    // if we didn't get a weekday name, mark the date as invalid
1333
    if (weekday != null) {
1334
        week.d = weekday;
1335
    } else {
1336
        getParsingFlags(config).invalidWeekday = input;
1337
    }
1338
});
1339

    
1340
addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
1341
    week[token] = toInt(input);
1342
});
1343

    
1344
// HELPERS
1345

    
1346
function parseWeekday(input, locale) {
1347
    if (typeof input !== 'string') {
1348
        return input;
1349
    }
1350

    
1351
    if (!isNaN(input)) {
1352
        return parseInt(input, 10);
1353
    }
1354

    
1355
    input = locale.weekdaysParse(input);
1356
    if (typeof input === 'number') {
1357
        return input;
1358
    }
1359

    
1360
    return null;
1361
}
1362

    
1363
function parseIsoWeekday(input, locale) {
1364
    if (typeof input === 'string') {
1365
        return locale.weekdaysParse(input) % 7 || 7;
1366
    }
1367
    return isNaN(input) ? null : input;
1368
}
1369

    
1370
// LOCALES
1371

    
1372
var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
1373
function localeWeekdays (m, format) {
1374
    if (!m) {
1375
        return isArray(this._weekdays) ? this._weekdays :
1376
            this._weekdays['standalone'];
1377
    }
1378
    return isArray(this._weekdays) ? this._weekdays[m.day()] :
1379
        this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
1380
}
1381

    
1382
var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
1383
function localeWeekdaysShort (m) {
1384
    return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
1385
}
1386

    
1387
var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
1388
function localeWeekdaysMin (m) {
1389
    return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
1390
}
1391

    
1392
function handleStrictParse$1(weekdayName, format, strict) {
1393
    var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
1394
    if (!this._weekdaysParse) {
1395
        this._weekdaysParse = [];
1396
        this._shortWeekdaysParse = [];
1397
        this._minWeekdaysParse = [];
1398

    
1399
        for (i = 0; i < 7; ++i) {
1400
            mom = createUTC([2000, 1]).day(i);
1401
            this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
1402
            this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
1403
            this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
1404
        }
1405
    }
1406

    
1407
    if (strict) {
1408
        if (format === 'dddd') {
1409
            ii = indexOf.call(this._weekdaysParse, llc);
1410
            return ii !== -1 ? ii : null;
1411
        } else if (format === 'ddd') {
1412
            ii = indexOf.call(this._shortWeekdaysParse, llc);
1413
            return ii !== -1 ? ii : null;
1414
        } else {
1415
            ii = indexOf.call(this._minWeekdaysParse, llc);
1416
            return ii !== -1 ? ii : null;
1417
        }
1418
    } else {
1419
        if (format === 'dddd') {
1420
            ii = indexOf.call(this._weekdaysParse, llc);
1421
            if (ii !== -1) {
1422
                return ii;
1423
            }
1424
            ii = indexOf.call(this._shortWeekdaysParse, llc);
1425
            if (ii !== -1) {
1426
                return ii;
1427
            }
1428
            ii = indexOf.call(this._minWeekdaysParse, llc);
1429
            return ii !== -1 ? ii : null;
1430
        } else if (format === 'ddd') {
1431
            ii = indexOf.call(this._shortWeekdaysParse, llc);
1432
            if (ii !== -1) {
1433
                return ii;
1434
            }
1435
            ii = indexOf.call(this._weekdaysParse, llc);
1436
            if (ii !== -1) {
1437
                return ii;
1438
            }
1439
            ii = indexOf.call(this._minWeekdaysParse, llc);
1440
            return ii !== -1 ? ii : null;
1441
        } else {
1442
            ii = indexOf.call(this._minWeekdaysParse, llc);
1443
            if (ii !== -1) {
1444
                return ii;
1445
            }
1446
            ii = indexOf.call(this._weekdaysParse, llc);
1447
            if (ii !== -1) {
1448
                return ii;
1449
            }
1450
            ii = indexOf.call(this._shortWeekdaysParse, llc);
1451
            return ii !== -1 ? ii : null;
1452
        }
1453
    }
1454
}
1455

    
1456
function localeWeekdaysParse (weekdayName, format, strict) {
1457
    var i, mom, regex;
1458

    
1459
    if (this._weekdaysParseExact) {
1460
        return handleStrictParse$1.call(this, weekdayName, format, strict);
1461
    }
1462

    
1463
    if (!this._weekdaysParse) {
1464
        this._weekdaysParse = [];
1465
        this._minWeekdaysParse = [];
1466
        this._shortWeekdaysParse = [];
1467
        this._fullWeekdaysParse = [];
1468
    }
1469

    
1470
    for (i = 0; i < 7; i++) {
1471
        // make the regex if we don't have it already
1472

    
1473
        mom = createUTC([2000, 1]).day(i);
1474
        if (strict && !this._fullWeekdaysParse[i]) {
1475
            this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
1476
            this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
1477
            this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
1478
        }
1479
        if (!this._weekdaysParse[i]) {
1480
            regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
1481
            this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
1482
        }
1483
        // test the regex
1484
        if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
1485
            return i;
1486
        } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
1487
            return i;
1488
        } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
1489
            return i;
1490
        } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
1491
            return i;
1492
        }
1493
    }
1494
}
1495

    
1496
// MOMENTS
1497

    
1498
function getSetDayOfWeek (input) {
1499
    if (!this.isValid()) {
1500
        return input != null ? this : NaN;
1501
    }
1502
    var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1503
    if (input != null) {
1504
        input = parseWeekday(input, this.localeData());
1505
        return this.add(input - day, 'd');
1506
    } else {
1507
        return day;
1508
    }
1509
}
1510

    
1511
function getSetLocaleDayOfWeek (input) {
1512
    if (!this.isValid()) {
1513
        return input != null ? this : NaN;
1514
    }
1515
    var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
1516
    return input == null ? weekday : this.add(input - weekday, 'd');
1517
}
1518

    
1519
function getSetISODayOfWeek (input) {
1520
    if (!this.isValid()) {
1521
        return input != null ? this : NaN;
1522
    }
1523

    
1524
    // behaves the same as moment#day except
1525
    // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
1526
    // as a setter, sunday should belong to the previous week.
1527

    
1528
    if (input != null) {
1529
        var weekday = parseIsoWeekday(input, this.localeData());
1530
        return this.day(this.day() % 7 ? weekday : weekday - 7);
1531
    } else {
1532
        return this.day() || 7;
1533
    }
1534
}
1535

    
1536
var defaultWeekdaysRegex = matchWord;
1537
function weekdaysRegex (isStrict) {
1538
    if (this._weekdaysParseExact) {
1539
        if (!hasOwnProp(this, '_weekdaysRegex')) {
1540
            computeWeekdaysParse.call(this);
1541
        }
1542
        if (isStrict) {
1543
            return this._weekdaysStrictRegex;
1544
        } else {
1545
            return this._weekdaysRegex;
1546
        }
1547
    } else {
1548
        if (!hasOwnProp(this, '_weekdaysRegex')) {
1549
            this._weekdaysRegex = defaultWeekdaysRegex;
1550
        }
1551
        return this._weekdaysStrictRegex && isStrict ?
1552
            this._weekdaysStrictRegex : this._weekdaysRegex;
1553
    }
1554
}
1555

    
1556
var defaultWeekdaysShortRegex = matchWord;
1557
function weekdaysShortRegex (isStrict) {
1558
    if (this._weekdaysParseExact) {
1559
        if (!hasOwnProp(this, '_weekdaysRegex')) {
1560
            computeWeekdaysParse.call(this);
1561
        }
1562
        if (isStrict) {
1563
            return this._weekdaysShortStrictRegex;
1564
        } else {
1565
            return this._weekdaysShortRegex;
1566
        }
1567
    } else {
1568
        if (!hasOwnProp(this, '_weekdaysShortRegex')) {
1569
            this._weekdaysShortRegex = defaultWeekdaysShortRegex;
1570
        }
1571
        return this._weekdaysShortStrictRegex && isStrict ?
1572
            this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
1573
    }
1574
}
1575

    
1576
var defaultWeekdaysMinRegex = matchWord;
1577
function weekdaysMinRegex (isStrict) {
1578
    if (this._weekdaysParseExact) {
1579
        if (!hasOwnProp(this, '_weekdaysRegex')) {
1580
            computeWeekdaysParse.call(this);
1581
        }
1582
        if (isStrict) {
1583
            return this._weekdaysMinStrictRegex;
1584
        } else {
1585
            return this._weekdaysMinRegex;
1586
        }
1587
    } else {
1588
        if (!hasOwnProp(this, '_weekdaysMinRegex')) {
1589
            this._weekdaysMinRegex = defaultWeekdaysMinRegex;
1590
        }
1591
        return this._weekdaysMinStrictRegex && isStrict ?
1592
            this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
1593
    }
1594
}
1595

    
1596

    
1597
function computeWeekdaysParse () {
1598
    function cmpLenRev(a, b) {
1599
        return b.length - a.length;
1600
    }
1601

    
1602
    var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
1603
        i, mom, minp, shortp, longp;
1604
    for (i = 0; i < 7; i++) {
1605
        // make the regex if we don't have it already
1606
        mom = createUTC([2000, 1]).day(i);
1607
        minp = this.weekdaysMin(mom, '');
1608
        shortp = this.weekdaysShort(mom, '');
1609
        longp = this.weekdays(mom, '');
1610
        minPieces.push(minp);
1611
        shortPieces.push(shortp);
1612
        longPieces.push(longp);
1613
        mixedPieces.push(minp);
1614
        mixedPieces.push(shortp);
1615
        mixedPieces.push(longp);
1616
    }
1617
    // Sorting makes sure if one weekday (or abbr) is a prefix of another it
1618
    // will match the longer piece.
1619
    minPieces.sort(cmpLenRev);
1620
    shortPieces.sort(cmpLenRev);
1621
    longPieces.sort(cmpLenRev);
1622
    mixedPieces.sort(cmpLenRev);
1623
    for (i = 0; i < 7; i++) {
1624
        shortPieces[i] = regexEscape(shortPieces[i]);
1625
        longPieces[i] = regexEscape(longPieces[i]);
1626
        mixedPieces[i] = regexEscape(mixedPieces[i]);
1627
    }
1628

    
1629
    this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1630
    this._weekdaysShortRegex = this._weekdaysRegex;
1631
    this._weekdaysMinRegex = this._weekdaysRegex;
1632

    
1633
    this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1634
    this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
1635
    this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
1636
}
1637

    
1638
// FORMATTING
1639

    
1640
function hFormat() {
1641
    return this.hours() % 12 || 12;
1642
}
1643

    
1644
function kFormat() {
1645
    return this.hours() || 24;
1646
}
1647

    
1648
addFormatToken('H', ['HH', 2], 0, 'hour');
1649
addFormatToken('h', ['hh', 2], 0, hFormat);
1650
addFormatToken('k', ['kk', 2], 0, kFormat);
1651

    
1652
addFormatToken('hmm', 0, 0, function () {
1653
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
1654
});
1655

    
1656
addFormatToken('hmmss', 0, 0, function () {
1657
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
1658
        zeroFill(this.seconds(), 2);
1659
});
1660

    
1661
addFormatToken('Hmm', 0, 0, function () {
1662
    return '' + this.hours() + zeroFill(this.minutes(), 2);
1663
});
1664

    
1665
addFormatToken('Hmmss', 0, 0, function () {
1666
    return '' + this.hours() + zeroFill(this.minutes(), 2) +
1667
        zeroFill(this.seconds(), 2);
1668
});
1669

    
1670
function meridiem (token, lowercase) {
1671
    addFormatToken(token, 0, 0, function () {
1672
        return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
1673
    });
1674
}
1675

    
1676
meridiem('a', true);
1677
meridiem('A', false);
1678

    
1679
// ALIASES
1680

    
1681
addUnitAlias('hour', 'h');
1682

    
1683
// PRIORITY
1684
addUnitPriority('hour', 13);
1685

    
1686
// PARSING
1687

    
1688
function matchMeridiem (isStrict, locale) {
1689
    return locale._meridiemParse;
1690
}
1691

    
1692
addRegexToken('a',  matchMeridiem);
1693
addRegexToken('A',  matchMeridiem);
1694
addRegexToken('H',  match1to2);
1695
addRegexToken('h',  match1to2);
1696
addRegexToken('k',  match1to2);
1697
addRegexToken('HH', match1to2, match2);
1698
addRegexToken('hh', match1to2, match2);
1699
addRegexToken('kk', match1to2, match2);
1700

    
1701
addRegexToken('hmm', match3to4);
1702
addRegexToken('hmmss', match5to6);
1703
addRegexToken('Hmm', match3to4);
1704
addRegexToken('Hmmss', match5to6);
1705

    
1706
addParseToken(['H', 'HH'], HOUR);
1707
addParseToken(['k', 'kk'], function (input, array, config) {
1708
    var kInput = toInt(input);
1709
    array[HOUR] = kInput === 24 ? 0 : kInput;
1710
});
1711
addParseToken(['a', 'A'], function (input, array, config) {
1712
    config._isPm = config._locale.isPM(input);
1713
    config._meridiem = input;
1714
});
1715
addParseToken(['h', 'hh'], function (input, array, config) {
1716
    array[HOUR] = toInt(input);
1717
    getParsingFlags(config).bigHour = true;
1718
});
1719
addParseToken('hmm', function (input, array, config) {
1720
    var pos = input.length - 2;
1721
    array[HOUR] = toInt(input.substr(0, pos));
1722
    array[MINUTE] = toInt(input.substr(pos));
1723
    getParsingFlags(config).bigHour = true;
1724
});
1725
addParseToken('hmmss', function (input, array, config) {
1726
    var pos1 = input.length - 4;
1727
    var pos2 = input.length - 2;
1728
    array[HOUR] = toInt(input.substr(0, pos1));
1729
    array[MINUTE] = toInt(input.substr(pos1, 2));
1730
    array[SECOND] = toInt(input.substr(pos2));
1731
    getParsingFlags(config).bigHour = true;
1732
});
1733
addParseToken('Hmm', function (input, array, config) {
1734
    var pos = input.length - 2;
1735
    array[HOUR] = toInt(input.substr(0, pos));
1736
    array[MINUTE] = toInt(input.substr(pos));
1737
});
1738
addParseToken('Hmmss', function (input, array, config) {
1739
    var pos1 = input.length - 4;
1740
    var pos2 = input.length - 2;
1741
    array[HOUR] = toInt(input.substr(0, pos1));
1742
    array[MINUTE] = toInt(input.substr(pos1, 2));
1743
    array[SECOND] = toInt(input.substr(pos2));
1744
});
1745

    
1746
// LOCALES
1747

    
1748
function localeIsPM (input) {
1749
    // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
1750
    // Using charAt should be more compatible.
1751
    return ((input + '').toLowerCase().charAt(0) === 'p');
1752
}
1753

    
1754
var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
1755
function localeMeridiem (hours, minutes, isLower) {
1756
    if (hours > 11) {
1757
        return isLower ? 'pm' : 'PM';
1758
    } else {
1759
        return isLower ? 'am' : 'AM';
1760
    }
1761
}
1762

    
1763

    
1764
// MOMENTS
1765

    
1766
// Setting the hour should keep the time, because the user explicitly
1767
// specified which hour he wants. So trying to maintain the same hour (in
1768
// a new timezone) makes sense. Adding/subtracting hours does not follow
1769
// this rule.
1770
var getSetHour = makeGetSet('Hours', true);
1771

    
1772
var baseConfig = {
1773
    calendar: defaultCalendar,
1774
    longDateFormat: defaultLongDateFormat,
1775
    invalidDate: defaultInvalidDate,
1776
    ordinal: defaultOrdinal,
1777
    dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
1778
    relativeTime: defaultRelativeTime,
1779

    
1780
    months: defaultLocaleMonths,
1781
    monthsShort: defaultLocaleMonthsShort,
1782

    
1783
    week: defaultLocaleWeek,
1784

    
1785
    weekdays: defaultLocaleWeekdays,
1786
    weekdaysMin: defaultLocaleWeekdaysMin,
1787
    weekdaysShort: defaultLocaleWeekdaysShort,
1788

    
1789
    meridiemParse: defaultLocaleMeridiemParse
1790
};
1791

    
1792
// internal storage for locale config files
1793
var locales = {};
1794
var localeFamilies = {};
1795
var globalLocale;
1796

    
1797
function normalizeLocale(key) {
1798
    return key ? key.toLowerCase().replace('_', '-') : key;
1799
}
1800

    
1801
// pick the locale from the array
1802
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
1803
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
1804
function chooseLocale(names) {
1805
    var i = 0, j, next, locale, split;
1806

    
1807
    while (i < names.length) {
1808
        split = normalizeLocale(names[i]).split('-');
1809
        j = split.length;
1810
        next = normalizeLocale(names[i + 1]);
1811
        next = next ? next.split('-') : null;
1812
        while (j > 0) {
1813
            locale = loadLocale(split.slice(0, j).join('-'));
1814
            if (locale) {
1815
                return locale;
1816
            }
1817
            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
1818
                //the next array item is better than a shallower substring of this one
1819
                break;
1820
            }
1821
            j--;
1822
        }
1823
        i++;
1824
    }
1825
    return globalLocale;
1826
}
1827

    
1828
function loadLocale(name) {
1829
    var oldLocale = null;
1830
    // TODO: Find a better way to register and load all the locales in Node
1831
    if (!locales[name] && (typeof module !== 'undefined') &&
1832
            module && module.exports) {
1833
        try {
1834
            oldLocale = globalLocale._abbr;
1835
            var aliasedRequire = require;
1836
            aliasedRequire('./locale/' + name);
1837
            getSetGlobalLocale(oldLocale);
1838
        } catch (e) {}
1839
    }
1840
    return locales[name];
1841
}
1842

    
1843
// This function will load locale and then set the global locale.  If
1844
// no arguments are passed in, it will simply return the current global
1845
// locale key.
1846
function getSetGlobalLocale (key, values) {
1847
    var data;
1848
    if (key) {
1849
        if (isUndefined(values)) {
1850
            data = getLocale(key);
1851
        }
1852
        else {
1853
            data = defineLocale(key, values);
1854
        }
1855

    
1856
        if (data) {
1857
            // moment.duration._locale = moment._locale = data;
1858
            globalLocale = data;
1859
        }
1860
        else {
1861
            if ((typeof console !==  'undefined') && console.warn) {
1862
                //warn user if arguments are passed but the locale could not be set
1863
                console.warn('Locale ' + key +  ' not found. Did you forget to load it?');
1864
            }
1865
        }
1866
    }
1867

    
1868
    return globalLocale._abbr;
1869
}
1870

    
1871
function defineLocale (name, config) {
1872
    if (config !== null) {
1873
        var locale, parentConfig = baseConfig;
1874
        config.abbr = name;
1875
        if (locales[name] != null) {
1876
            deprecateSimple('defineLocaleOverride',
1877
                    'use moment.updateLocale(localeName, config) to change ' +
1878
                    'an existing locale. moment.defineLocale(localeName, ' +
1879
                    'config) should only be used for creating a new locale ' +
1880
                    'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
1881
            parentConfig = locales[name]._config;
1882
        } else if (config.parentLocale != null) {
1883
            if (locales[config.parentLocale] != null) {
1884
                parentConfig = locales[config.parentLocale]._config;
1885
            } else {
1886
                locale = loadLocale(config.parentLocale);
1887
                if (locale != null) {
1888
                    parentConfig = locale._config;
1889
                } else {
1890
                    if (!localeFamilies[config.parentLocale]) {
1891
                        localeFamilies[config.parentLocale] = [];
1892
                    }
1893
                    localeFamilies[config.parentLocale].push({
1894
                        name: name,
1895
                        config: config
1896
                    });
1897
                    return null;
1898
                }
1899
            }
1900
        }
1901
        locales[name] = new Locale(mergeConfigs(parentConfig, config));
1902

    
1903
        if (localeFamilies[name]) {
1904
            localeFamilies[name].forEach(function (x) {
1905
                defineLocale(x.name, x.config);
1906
            });
1907
        }
1908

    
1909
        // backwards compat for now: also set the locale
1910
        // make sure we set the locale AFTER all child locales have been
1911
        // created, so we won't end up with the child locale set.
1912
        getSetGlobalLocale(name);
1913

    
1914

    
1915
        return locales[name];
1916
    } else {
1917
        // useful for testing
1918
        delete locales[name];
1919
        return null;
1920
    }
1921
}
1922

    
1923
function updateLocale(name, config) {
1924
    if (config != null) {
1925
        var locale, tmpLocale, parentConfig = baseConfig;
1926
        // MERGE
1927
        tmpLocale = loadLocale(name);
1928
        if (tmpLocale != null) {
1929
            parentConfig = tmpLocale._config;
1930
        }
1931
        config = mergeConfigs(parentConfig, config);
1932
        locale = new Locale(config);
1933
        locale.parentLocale = locales[name];
1934
        locales[name] = locale;
1935

    
1936
        // backwards compat for now: also set the locale
1937
        getSetGlobalLocale(name);
1938
    } else {
1939
        // pass null for config to unupdate, useful for tests
1940
        if (locales[name] != null) {
1941
            if (locales[name].parentLocale != null) {
1942
                locales[name] = locales[name].parentLocale;
1943
            } else if (locales[name] != null) {
1944
                delete locales[name];
1945
            }
1946
        }
1947
    }
1948
    return locales[name];
1949
}
1950

    
1951
// returns locale data
1952
function getLocale (key) {
1953
    var locale;
1954

    
1955
    if (key && key._locale && key._locale._abbr) {
1956
        key = key._locale._abbr;
1957
    }
1958

    
1959
    if (!key) {
1960
        return globalLocale;
1961
    }
1962

    
1963
    if (!isArray(key)) {
1964
        //short-circuit everything else
1965
        locale = loadLocale(key);
1966
        if (locale) {
1967
            return locale;
1968
        }
1969
        key = [key];
1970
    }
1971

    
1972
    return chooseLocale(key);
1973
}
1974

    
1975
function listLocales() {
1976
    return keys(locales);
1977
}
1978

    
1979
function checkOverflow (m) {
1980
    var overflow;
1981
    var a = m._a;
1982

    
1983
    if (a && getParsingFlags(m).overflow === -2) {
1984
        overflow =
1985
            a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
1986
            a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
1987
            a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
1988
            a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
1989
            a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
1990
            a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
1991
            -1;
1992

    
1993
        if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
1994
            overflow = DATE;
1995
        }
1996
        if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
1997
            overflow = WEEK;
1998
        }
1999
        if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
2000
            overflow = WEEKDAY;
2001
        }
2002

    
2003
        getParsingFlags(m).overflow = overflow;
2004
    }
2005

    
2006
    return m;
2007
}
2008

    
2009
// Pick the first defined of two or three arguments.
2010
function defaults(a, b, c) {
2011
    if (a != null) {
2012
        return a;
2013
    }
2014
    if (b != null) {
2015
        return b;
2016
    }
2017
    return c;
2018
}
2019

    
2020
function currentDateArray(config) {
2021
    // hooks is actually the exported moment object
2022
    var nowValue = new Date(hooks.now());
2023
    if (config._useUTC) {
2024
        return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
2025
    }
2026
    return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
2027
}
2028

    
2029
// convert an array to a date.
2030
// the array should mirror the parameters below
2031
// note: all values past the year are optional and will default to the lowest possible value.
2032
// [year, month, day , hour, minute, second, millisecond]
2033
function configFromArray (config) {
2034
    var i, date, input = [], currentDate, expectedWeekday, yearToUse;
2035

    
2036
    if (config._d) {
2037
        return;
2038
    }
2039

    
2040
    currentDate = currentDateArray(config);
2041

    
2042
    //compute day of the year from weeks and weekdays
2043
    if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
2044
        dayOfYearFromWeekInfo(config);
2045
    }
2046

    
2047
    //if the day of the year is set, figure out what it is
2048
    if (config._dayOfYear != null) {
2049
        yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
2050

    
2051
        if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
2052
            getParsingFlags(config)._overflowDayOfYear = true;
2053
        }
2054

    
2055
        date = createUTCDate(yearToUse, 0, config._dayOfYear);
2056
        config._a[MONTH] = date.getUTCMonth();
2057
        config._a[DATE] = date.getUTCDate();
2058
    }
2059

    
2060
    // Default to current date.
2061
    // * if no year, month, day of month are given, default to today
2062
    // * if day of month is given, default month and year
2063
    // * if month is given, default only year
2064
    // * if year is given, don't default anything
2065
    for (i = 0; i < 3 && config._a[i] == null; ++i) {
2066
        config._a[i] = input[i] = currentDate[i];
2067
    }
2068

    
2069
    // Zero out whatever was not defaulted, including time
2070
    for (; i < 7; i++) {
2071
        config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
2072
    }
2073

    
2074
    // Check for 24:00:00.000
2075
    if (config._a[HOUR] === 24 &&
2076
            config._a[MINUTE] === 0 &&
2077
            config._a[SECOND] === 0 &&
2078
            config._a[MILLISECOND] === 0) {
2079
        config._nextDay = true;
2080
        config._a[HOUR] = 0;
2081
    }
2082

    
2083
    config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
2084
    expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
2085

    
2086
    // Apply timezone offset from input. The actual utcOffset can be changed
2087
    // with parseZone.
2088
    if (config._tzm != null) {
2089
        config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
2090
    }
2091

    
2092
    if (config._nextDay) {
2093
        config._a[HOUR] = 24;
2094
    }
2095

    
2096
    // check for mismatching day of week
2097
    if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
2098
        getParsingFlags(config).weekdayMismatch = true;
2099
    }
2100
}
2101

    
2102
function dayOfYearFromWeekInfo(config) {
2103
    var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
2104

    
2105
    w = config._w;
2106
    if (w.GG != null || w.W != null || w.E != null) {
2107
        dow = 1;
2108
        doy = 4;
2109

    
2110
        // TODO: We need to take the current isoWeekYear, but that depends on
2111
        // how we interpret now (local, utc, fixed offset). So create
2112
        // a now version of current config (take local/utc/offset flags, and
2113
        // create now).
2114
        weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
2115
        week = defaults(w.W, 1);
2116
        weekday = defaults(w.E, 1);
2117
        if (weekday < 1 || weekday > 7) {
2118
            weekdayOverflow = true;
2119
        }
2120
    } else {
2121
        dow = config._locale._week.dow;
2122
        doy = config._locale._week.doy;
2123

    
2124
        var curWeek = weekOfYear(createLocal(), dow, doy);
2125

    
2126
        weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
2127

    
2128
        // Default to current week.
2129
        week = defaults(w.w, curWeek.week);
2130

    
2131
        if (w.d != null) {
2132
            // weekday -- low day numbers are considered next week
2133
            weekday = w.d;
2134
            if (weekday < 0 || weekday > 6) {
2135
                weekdayOverflow = true;
2136
            }
2137
        } else if (w.e != null) {
2138
            // local weekday -- counting starts from begining of week
2139
            weekday = w.e + dow;
2140
            if (w.e < 0 || w.e > 6) {
2141
                weekdayOverflow = true;
2142
            }
2143
        } else {
2144
            // default to begining of week
2145
            weekday = dow;
2146
        }
2147
    }
2148
    if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
2149
        getParsingFlags(config)._overflowWeeks = true;
2150
    } else if (weekdayOverflow != null) {
2151
        getParsingFlags(config)._overflowWeekday = true;
2152
    } else {
2153
        temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
2154
        config._a[YEAR] = temp.year;
2155
        config._dayOfYear = temp.dayOfYear;
2156
    }
2157
}
2158

    
2159
// iso 8601 regex
2160
// 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)
2161
var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
2162
var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
2163

    
2164
var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
2165

    
2166
var isoDates = [
2167
    ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
2168
    ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
2169
    ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
2170
    ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
2171
    ['YYYY-DDD', /\d{4}-\d{3}/],
2172
    ['YYYY-MM', /\d{4}-\d\d/, false],
2173
    ['YYYYYYMMDD', /[+-]\d{10}/],
2174
    ['YYYYMMDD', /\d{8}/],
2175
    // YYYYMM is NOT allowed by the standard
2176
    ['GGGG[W]WWE', /\d{4}W\d{3}/],
2177
    ['GGGG[W]WW', /\d{4}W\d{2}/, false],
2178
    ['YYYYDDD', /\d{7}/]
2179
];
2180

    
2181
// iso time formats and regexes
2182
var isoTimes = [
2183
    ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
2184
    ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
2185
    ['HH:mm:ss', /\d\d:\d\d:\d\d/],
2186
    ['HH:mm', /\d\d:\d\d/],
2187
    ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
2188
    ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
2189
    ['HHmmss', /\d\d\d\d\d\d/],
2190
    ['HHmm', /\d\d\d\d/],
2191
    ['HH', /\d\d/]
2192
];
2193

    
2194
var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
2195

    
2196
// date from iso format
2197
function configFromISO(config) {
2198
    var i, l,
2199
        string = config._i,
2200
        match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
2201
        allowTime, dateFormat, timeFormat, tzFormat;
2202

    
2203
    if (match) {
2204
        getParsingFlags(config).iso = true;
2205

    
2206
        for (i = 0, l = isoDates.length; i < l; i++) {
2207
            if (isoDates[i][1].exec(match[1])) {
2208
                dateFormat = isoDates[i][0];
2209
                allowTime = isoDates[i][2] !== false;
2210
                break;
2211
            }
2212
        }
2213
        if (dateFormat == null) {
2214
            config._isValid = false;
2215
            return;
2216
        }
2217
        if (match[3]) {
2218
            for (i = 0, l = isoTimes.length; i < l; i++) {
2219
                if (isoTimes[i][1].exec(match[3])) {
2220
                    // match[2] should be 'T' or space
2221
                    timeFormat = (match[2] || ' ') + isoTimes[i][0];
2222
                    break;
2223
                }
2224
            }
2225
            if (timeFormat == null) {
2226
                config._isValid = false;
2227
                return;
2228
            }
2229
        }
2230
        if (!allowTime && timeFormat != null) {
2231
            config._isValid = false;
2232
            return;
2233
        }
2234
        if (match[4]) {
2235
            if (tzRegex.exec(match[4])) {
2236
                tzFormat = 'Z';
2237
            } else {
2238
                config._isValid = false;
2239
                return;
2240
            }
2241
        }
2242
        config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
2243
        configFromStringAndFormat(config);
2244
    } else {
2245
        config._isValid = false;
2246
    }
2247
}
2248

    
2249
// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
2250
var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
2251

    
2252
function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
2253
    var result = [
2254
        untruncateYear(yearStr),
2255
        defaultLocaleMonthsShort.indexOf(monthStr),
2256
        parseInt(dayStr, 10),
2257
        parseInt(hourStr, 10),
2258
        parseInt(minuteStr, 10)
2259
    ];
2260

    
2261
    if (secondStr) {
2262
        result.push(parseInt(secondStr, 10));
2263
    }
2264

    
2265
    return result;
2266
}
2267

    
2268
function untruncateYear(yearStr) {
2269
    var year = parseInt(yearStr, 10);
2270
    if (year <= 49) {
2271
        return 2000 + year;
2272
    } else if (year <= 999) {
2273
        return 1900 + year;
2274
    }
2275
    return year;
2276
}
2277

    
2278
function preprocessRFC2822(s) {
2279
    // Remove comments and folding whitespace and replace multiple-spaces with a single space
2280
    return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').trim();
2281
}
2282

    
2283
function checkWeekday(weekdayStr, parsedInput, config) {
2284
    if (weekdayStr) {
2285
        // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
2286
        var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
2287
            weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
2288
        if (weekdayProvided !== weekdayActual) {
2289
            getParsingFlags(config).weekdayMismatch = true;
2290
            config._isValid = false;
2291
            return false;
2292
        }
2293
    }
2294
    return true;
2295
}
2296

    
2297
var obsOffsets = {
2298
    UT: 0,
2299
    GMT: 0,
2300
    EDT: -4 * 60,
2301
    EST: -5 * 60,
2302
    CDT: -5 * 60,
2303
    CST: -6 * 60,
2304
    MDT: -6 * 60,
2305
    MST: -7 * 60,
2306
    PDT: -7 * 60,
2307
    PST: -8 * 60
2308
};
2309

    
2310
function calculateOffset(obsOffset, militaryOffset, numOffset) {
2311
    if (obsOffset) {
2312
        return obsOffsets[obsOffset];
2313
    } else if (militaryOffset) {
2314
        // the only allowed military tz is Z
2315
        return 0;
2316
    } else {
2317
        var hm = parseInt(numOffset, 10);
2318
        var m = hm % 100, h = (hm - m) / 100;
2319
        return h * 60 + m;
2320
    }
2321
}
2322

    
2323
// date and time from ref 2822 format
2324
function configFromRFC2822(config) {
2325
    var match = rfc2822.exec(preprocessRFC2822(config._i));
2326
    if (match) {
2327
        var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
2328
        if (!checkWeekday(match[1], parsedArray, config)) {
2329
            return;
2330
        }
2331

    
2332
        config._a = parsedArray;
2333
        config._tzm = calculateOffset(match[8], match[9], match[10]);
2334

    
2335
        config._d = createUTCDate.apply(null, config._a);
2336
        config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
2337

    
2338
        getParsingFlags(config).rfc2822 = true;
2339
    } else {
2340
        config._isValid = false;
2341
    }
2342
}
2343

    
2344
// date from iso format or fallback
2345
function configFromString(config) {
2346
    var matched = aspNetJsonRegex.exec(config._i);
2347

    
2348
    if (matched !== null) {
2349
        config._d = new Date(+matched[1]);
2350
        return;
2351
    }
2352

    
2353
    configFromISO(config);
2354
    if (config._isValid === false) {
2355
        delete config._isValid;
2356
    } else {
2357
        return;
2358
    }
2359

    
2360
    configFromRFC2822(config);
2361
    if (config._isValid === false) {
2362
        delete config._isValid;
2363
    } else {
2364
        return;
2365
    }
2366

    
2367
    // Final attempt, use Input Fallback
2368
    hooks.createFromInputFallback(config);
2369
}
2370

    
2371
hooks.createFromInputFallback = deprecate(
2372
    'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
2373
    'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
2374
    'discouraged and will be removed in an upcoming major release. Please refer to ' +
2375
    'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
2376
    function (config) {
2377
        config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
2378
    }
2379
);
2380

    
2381
// constant that refers to the ISO standard
2382
hooks.ISO_8601 = function () {};
2383

    
2384
// constant that refers to the RFC 2822 form
2385
hooks.RFC_2822 = function () {};
2386

    
2387
// date from string and format string
2388
function configFromStringAndFormat(config) {
2389
    // TODO: Move this to another part of the creation flow to prevent circular deps
2390
    if (config._f === hooks.ISO_8601) {
2391
        configFromISO(config);
2392
        return;
2393
    }
2394
    if (config._f === hooks.RFC_2822) {
2395
        configFromRFC2822(config);
2396
        return;
2397
    }
2398
    config._a = [];
2399
    getParsingFlags(config).empty = true;
2400

    
2401
    // This array is used to make a Date, either with `new Date` or `Date.UTC`
2402
    var string = '' + config._i,
2403
        i, parsedInput, tokens, token, skipped,
2404
        stringLength = string.length,
2405
        totalParsedInputLength = 0;
2406

    
2407
    tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
2408

    
2409
    for (i = 0; i < tokens.length; i++) {
2410
        token = tokens[i];
2411
        parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
2412
        // console.log('token', token, 'parsedInput', parsedInput,
2413
        //         'regex', getParseRegexForToken(token, config));
2414
        if (parsedInput) {
2415
            skipped = string.substr(0, string.indexOf(parsedInput));
2416
            if (skipped.length > 0) {
2417
                getParsingFlags(config).unusedInput.push(skipped);
2418
            }
2419
            string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
2420
            totalParsedInputLength += parsedInput.length;
2421
        }
2422
        // don't parse if it's not a known token
2423
        if (formatTokenFunctions[token]) {
2424
            if (parsedInput) {
2425
                getParsingFlags(config).empty = false;
2426
            }
2427
            else {
2428
                getParsingFlags(config).unusedTokens.push(token);
2429
            }
2430
            addTimeToArrayFromToken(token, parsedInput, config);
2431
        }
2432
        else if (config._strict && !parsedInput) {
2433
            getParsingFlags(config).unusedTokens.push(token);
2434
        }
2435
    }
2436

    
2437
    // add remaining unparsed input length to the string
2438
    getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
2439
    if (string.length > 0) {
2440
        getParsingFlags(config).unusedInput.push(string);
2441
    }
2442

    
2443
    // clear _12h flag if hour is <= 12
2444
    if (config._a[HOUR] <= 12 &&
2445
        getParsingFlags(config).bigHour === true &&
2446
        config._a[HOUR] > 0) {
2447
        getParsingFlags(config).bigHour = undefined;
2448
    }
2449

    
2450
    getParsingFlags(config).parsedDateParts = config._a.slice(0);
2451
    getParsingFlags(config).meridiem = config._meridiem;
2452
    // handle meridiem
2453
    config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
2454

    
2455
    configFromArray(config);
2456
    checkOverflow(config);
2457
}
2458

    
2459

    
2460
function meridiemFixWrap (locale, hour, meridiem) {
2461
    var isPm;
2462

    
2463
    if (meridiem == null) {
2464
        // nothing to do
2465
        return hour;
2466
    }
2467
    if (locale.meridiemHour != null) {
2468
        return locale.meridiemHour(hour, meridiem);
2469
    } else if (locale.isPM != null) {
2470
        // Fallback
2471
        isPm = locale.isPM(meridiem);
2472
        if (isPm && hour < 12) {
2473
            hour += 12;
2474
        }
2475
        if (!isPm && hour === 12) {
2476
            hour = 0;
2477
        }
2478
        return hour;
2479
    } else {
2480
        // this is not supposed to happen
2481
        return hour;
2482
    }
2483
}
2484

    
2485
// date from string and array of format strings
2486
function configFromStringAndArray(config) {
2487
    var tempConfig,
2488
        bestMoment,
2489

    
2490
        scoreToBeat,
2491
        i,
2492
        currentScore;
2493

    
2494
    if (config._f.length === 0) {
2495
        getParsingFlags(config).invalidFormat = true;
2496
        config._d = new Date(NaN);
2497
        return;
2498
    }
2499

    
2500
    for (i = 0; i < config._f.length; i++) {
2501
        currentScore = 0;
2502
        tempConfig = copyConfig({}, config);
2503
        if (config._useUTC != null) {
2504
            tempConfig._useUTC = config._useUTC;
2505
        }
2506
        tempConfig._f = config._f[i];
2507
        configFromStringAndFormat(tempConfig);
2508

    
2509
        if (!isValid(tempConfig)) {
2510
            continue;
2511
        }
2512

    
2513
        // if there is any input that was not parsed add a penalty for that format
2514
        currentScore += getParsingFlags(tempConfig).charsLeftOver;
2515

    
2516
        //or tokens
2517
        currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
2518

    
2519
        getParsingFlags(tempConfig).score = currentScore;
2520

    
2521
        if (scoreToBeat == null || currentScore < scoreToBeat) {
2522
            scoreToBeat = currentScore;
2523
            bestMoment = tempConfig;
2524
        }
2525
    }
2526

    
2527
    extend(config, bestMoment || tempConfig);
2528
}
2529

    
2530
function configFromObject(config) {
2531
    if (config._d) {
2532
        return;
2533
    }
2534

    
2535
    var i = normalizeObjectUnits(config._i);
2536
    config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
2537
        return obj && parseInt(obj, 10);
2538
    });
2539

    
2540
    configFromArray(config);
2541
}
2542

    
2543
function createFromConfig (config) {
2544
    var res = new Moment(checkOverflow(prepareConfig(config)));
2545
    if (res._nextDay) {
2546
        // Adding is smart enough around DST
2547
        res.add(1, 'd');
2548
        res._nextDay = undefined;
2549
    }
2550

    
2551
    return res;
2552
}
2553

    
2554
function prepareConfig (config) {
2555
    var input = config._i,
2556
        format = config._f;
2557

    
2558
    config._locale = config._locale || getLocale(config._l);
2559

    
2560
    if (input === null || (format === undefined && input === '')) {
2561
        return createInvalid({nullInput: true});
2562
    }
2563

    
2564
    if (typeof input === 'string') {
2565
        config._i = input = config._locale.preparse(input);
2566
    }
2567

    
2568
    if (isMoment(input)) {
2569
        return new Moment(checkOverflow(input));
2570
    } else if (isDate(input)) {
2571
        config._d = input;
2572
    } else if (isArray(format)) {
2573
        configFromStringAndArray(config);
2574
    } else if (format) {
2575
        configFromStringAndFormat(config);
2576
    }  else {
2577
        configFromInput(config);
2578
    }
2579

    
2580
    if (!isValid(config)) {
2581
        config._d = null;
2582
    }
2583

    
2584
    return config;
2585
}
2586

    
2587
function configFromInput(config) {
2588
    var input = config._i;
2589
    if (isUndefined(input)) {
2590
        config._d = new Date(hooks.now());
2591
    } else if (isDate(input)) {
2592
        config._d = new Date(input.valueOf());
2593
    } else if (typeof input === 'string') {
2594
        configFromString(config);
2595
    } else if (isArray(input)) {
2596
        config._a = map(input.slice(0), function (obj) {
2597
            return parseInt(obj, 10);
2598
        });
2599
        configFromArray(config);
2600
    } else if (isObject(input)) {
2601
        configFromObject(config);
2602
    } else if (isNumber(input)) {
2603
        // from milliseconds
2604
        config._d = new Date(input);
2605
    } else {
2606
        hooks.createFromInputFallback(config);
2607
    }
2608
}
2609

    
2610
function createLocalOrUTC (input, format, locale, strict, isUTC) {
2611
    var c = {};
2612

    
2613
    if (locale === true || locale === false) {
2614
        strict = locale;
2615
        locale = undefined;
2616
    }
2617

    
2618
    if ((isObject(input) && isObjectEmpty(input)) ||
2619
            (isArray(input) && input.length === 0)) {
2620
        input = undefined;
2621
    }
2622
    // object construction must be done this way.
2623
    // https://github.com/moment/moment/issues/1423
2624
    c._isAMomentObject = true;
2625
    c._useUTC = c._isUTC = isUTC;
2626
    c._l = locale;
2627
    c._i = input;
2628
    c._f = format;
2629
    c._strict = strict;
2630

    
2631
    return createFromConfig(c);
2632
}
2633

    
2634
function createLocal (input, format, locale, strict) {
2635
    return createLocalOrUTC(input, format, locale, strict, false);
2636
}
2637

    
2638
var prototypeMin = deprecate(
2639
    'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
2640
    function () {
2641
        var other = createLocal.apply(null, arguments);
2642
        if (this.isValid() && other.isValid()) {
2643
            return other < this ? this : other;
2644
        } else {
2645
            return createInvalid();
2646
        }
2647
    }
2648
);
2649

    
2650
var prototypeMax = deprecate(
2651
    'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
2652
    function () {
2653
        var other = createLocal.apply(null, arguments);
2654
        if (this.isValid() && other.isValid()) {
2655
            return other > this ? this : other;
2656
        } else {
2657
            return createInvalid();
2658
        }
2659
    }
2660
);
2661

    
2662
// Pick a moment m from moments so that m[fn](other) is true for all
2663
// other. This relies on the function fn to be transitive.
2664
//
2665
// moments should either be an array of moment objects or an array, whose
2666
// first element is an array of moment objects.
2667
function pickBy(fn, moments) {
2668
    var res, i;
2669
    if (moments.length === 1 && isArray(moments[0])) {
2670
        moments = moments[0];
2671
    }
2672
    if (!moments.length) {
2673
        return createLocal();
2674
    }
2675
    res = moments[0];
2676
    for (i = 1; i < moments.length; ++i) {
2677
        if (!moments[i].isValid() || moments[i][fn](res)) {
2678
            res = moments[i];
2679
        }
2680
    }
2681
    return res;
2682
}
2683

    
2684
// TODO: Use [].sort instead?
2685
function min () {
2686
    var args = [].slice.call(arguments, 0);
2687

    
2688
    return pickBy('isBefore', args);
2689
}
2690

    
2691
function max () {
2692
    var args = [].slice.call(arguments, 0);
2693

    
2694
    return pickBy('isAfter', args);
2695
}
2696

    
2697
var now = function () {
2698
    return Date.now ? Date.now() : +(new Date());
2699
};
2700

    
2701
var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
2702

    
2703
function isDurationValid(m) {
2704
    for (var key in m) {
2705
        if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
2706
            return false;
2707
        }
2708
    }
2709

    
2710
    var unitHasDecimal = false;
2711
    for (var i = 0; i < ordering.length; ++i) {
2712
        if (m[ordering[i]]) {
2713
            if (unitHasDecimal) {
2714
                return false; // only allow non-integers for smallest unit
2715
            }
2716
            if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
2717
                unitHasDecimal = true;
2718
            }
2719
        }
2720
    }
2721

    
2722
    return true;
2723
}
2724

    
2725
function isValid$1() {
2726
    return this._isValid;
2727
}
2728

    
2729
function createInvalid$1() {
2730
    return createDuration(NaN);
2731
}
2732

    
2733
function Duration (duration) {
2734
    var normalizedInput = normalizeObjectUnits(duration),
2735
        years = normalizedInput.year || 0,
2736
        quarters = normalizedInput.quarter || 0,
2737
        months = normalizedInput.month || 0,
2738
        weeks = normalizedInput.week || 0,
2739
        days = normalizedInput.day || 0,
2740
        hours = normalizedInput.hour || 0,
2741
        minutes = normalizedInput.minute || 0,
2742
        seconds = normalizedInput.second || 0,
2743
        milliseconds = normalizedInput.millisecond || 0;
2744

    
2745
    this._isValid = isDurationValid(normalizedInput);
2746

    
2747
    // representation for dateAddRemove
2748
    this._milliseconds = +milliseconds +
2749
        seconds * 1e3 + // 1000
2750
        minutes * 6e4 + // 1000 * 60
2751
        hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
2752
    // Because of dateAddRemove treats 24 hours as different from a
2753
    // day when working around DST, we need to store them separately
2754
    this._days = +days +
2755
        weeks * 7;
2756
    // It is impossible to translate months into days without knowing
2757
    // which months you are are talking about, so we have to store
2758
    // it separately.
2759
    this._months = +months +
2760
        quarters * 3 +
2761
        years * 12;
2762

    
2763
    this._data = {};
2764

    
2765
    this._locale = getLocale();
2766

    
2767
    this._bubble();
2768
}
2769

    
2770
function isDuration (obj) {
2771
    return obj instanceof Duration;
2772
}
2773

    
2774
function absRound (number) {
2775
    if (number < 0) {
2776
        return Math.round(-1 * number) * -1;
2777
    } else {
2778
        return Math.round(number);
2779
    }
2780
}
2781

    
2782
// FORMATTING
2783

    
2784
function offset (token, separator) {
2785
    addFormatToken(token, 0, 0, function () {
2786
        var offset = this.utcOffset();
2787
        var sign = '+';
2788
        if (offset < 0) {
2789
            offset = -offset;
2790
            sign = '-';
2791
        }
2792
        return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
2793
    });
2794
}
2795

    
2796
offset('Z', ':');
2797
offset('ZZ', '');
2798

    
2799
// PARSING
2800

    
2801
addRegexToken('Z',  matchShortOffset);
2802
addRegexToken('ZZ', matchShortOffset);
2803
addParseToken(['Z', 'ZZ'], function (input, array, config) {
2804
    config._useUTC = true;
2805
    config._tzm = offsetFromString(matchShortOffset, input);
2806
});
2807

    
2808
// HELPERS
2809

    
2810
// timezone chunker
2811
// '+10:00' > ['10',  '00']
2812
// '-1530'  > ['-15', '30']
2813
var chunkOffset = /([\+\-]|\d\d)/gi;
2814

    
2815
function offsetFromString(matcher, string) {
2816
    var matches = (string || '').match(matcher);
2817

    
2818
    if (matches === null) {
2819
        return null;
2820
    }
2821

    
2822
    var chunk   = matches[matches.length - 1] || [];
2823
    var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
2824
    var minutes = +(parts[1] * 60) + toInt(parts[2]);
2825

    
2826
    return minutes === 0 ?
2827
      0 :
2828
      parts[0] === '+' ? minutes : -minutes;
2829
}
2830

    
2831
// Return a moment from input, that is local/utc/zone equivalent to model.
2832
function cloneWithOffset(input, model) {
2833
    var res, diff;
2834
    if (model._isUTC) {
2835
        res = model.clone();
2836
        diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
2837
        // Use low-level api, because this fn is low-level api.
2838
        res._d.setTime(res._d.valueOf() + diff);
2839
        hooks.updateOffset(res, false);
2840
        return res;
2841
    } else {
2842
        return createLocal(input).local();
2843
    }
2844
}
2845

    
2846
function getDateOffset (m) {
2847
    // On Firefox.24 Date#getTimezoneOffset returns a floating point.
2848
    // https://github.com/moment/moment/pull/1871
2849
    return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
2850
}
2851

    
2852
// HOOKS
2853

    
2854
// This function will be called whenever a moment is mutated.
2855
// It is intended to keep the offset in sync with the timezone.
2856
hooks.updateOffset = function () {};
2857

    
2858
// MOMENTS
2859

    
2860
// keepLocalTime = true means only change the timezone, without
2861
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
2862
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
2863
// +0200, so we adjust the time as needed, to be valid.
2864
//
2865
// Keeping the time actually adds/subtracts (one hour)
2866
// from the actual represented time. That is why we call updateOffset
2867
// a second time. In case it wants us to change the offset again
2868
// _changeInProgress == true case, then we have to adjust, because
2869
// there is no such time in the given timezone.
2870
function getSetOffset (input, keepLocalTime, keepMinutes) {
2871
    var offset = this._offset || 0,
2872
        localAdjust;
2873
    if (!this.isValid()) {
2874
        return input != null ? this : NaN;
2875
    }
2876
    if (input != null) {
2877
        if (typeof input === 'string') {
2878
            input = offsetFromString(matchShortOffset, input);
2879
            if (input === null) {
2880
                return this;
2881
            }
2882
        } else if (Math.abs(input) < 16 && !keepMinutes) {
2883
            input = input * 60;
2884
        }
2885
        if (!this._isUTC && keepLocalTime) {
2886
            localAdjust = getDateOffset(this);
2887
        }
2888
        this._offset = input;
2889
        this._isUTC = true;
2890
        if (localAdjust != null) {
2891
            this.add(localAdjust, 'm');
2892
        }
2893
        if (offset !== input) {
2894
            if (!keepLocalTime || this._changeInProgress) {
2895
                addSubtract(this, createDuration(input - offset, 'm'), 1, false);
2896
            } else if (!this._changeInProgress) {
2897
                this._changeInProgress = true;
2898
                hooks.updateOffset(this, true);
2899
                this._changeInProgress = null;
2900
            }
2901
        }
2902
        return this;
2903
    } else {
2904
        return this._isUTC ? offset : getDateOffset(this);
2905
    }
2906
}
2907

    
2908
function getSetZone (input, keepLocalTime) {
2909
    if (input != null) {
2910
        if (typeof input !== 'string') {
2911
            input = -input;
2912
        }
2913

    
2914
        this.utcOffset(input, keepLocalTime);
2915

    
2916
        return this;
2917
    } else {
2918
        return -this.utcOffset();
2919
    }
2920
}
2921

    
2922
function setOffsetToUTC (keepLocalTime) {
2923
    return this.utcOffset(0, keepLocalTime);
2924
}
2925

    
2926
function setOffsetToLocal (keepLocalTime) {
2927
    if (this._isUTC) {
2928
        this.utcOffset(0, keepLocalTime);
2929
        this._isUTC = false;
2930

    
2931
        if (keepLocalTime) {
2932
            this.subtract(getDateOffset(this), 'm');
2933
        }
2934
    }
2935
    return this;
2936
}
2937

    
2938
function setOffsetToParsedOffset () {
2939
    if (this._tzm != null) {
2940
        this.utcOffset(this._tzm, false, true);
2941
    } else if (typeof this._i === 'string') {
2942
        var tZone = offsetFromString(matchOffset, this._i);
2943
        if (tZone != null) {
2944
            this.utcOffset(tZone);
2945
        }
2946
        else {
2947
            this.utcOffset(0, true);
2948
        }
2949
    }
2950
    return this;
2951
}
2952

    
2953
function hasAlignedHourOffset (input) {
2954
    if (!this.isValid()) {
2955
        return false;
2956
    }
2957
    input = input ? createLocal(input).utcOffset() : 0;
2958

    
2959
    return (this.utcOffset() - input) % 60 === 0;
2960
}
2961

    
2962
function isDaylightSavingTime () {
2963
    return (
2964
        this.utcOffset() > this.clone().month(0).utcOffset() ||
2965
        this.utcOffset() > this.clone().month(5).utcOffset()
2966
    );
2967
}
2968

    
2969
function isDaylightSavingTimeShifted () {
2970
    if (!isUndefined(this._isDSTShifted)) {
2971
        return this._isDSTShifted;
2972
    }
2973

    
2974
    var c = {};
2975

    
2976
    copyConfig(c, this);
2977
    c = prepareConfig(c);
2978

    
2979
    if (c._a) {
2980
        var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
2981
        this._isDSTShifted = this.isValid() &&
2982
            compareArrays(c._a, other.toArray()) > 0;
2983
    } else {
2984
        this._isDSTShifted = false;
2985
    }
2986

    
2987
    return this._isDSTShifted;
2988
}
2989

    
2990
function isLocal () {
2991
    return this.isValid() ? !this._isUTC : false;
2992
}
2993

    
2994
function isUtcOffset () {
2995
    return this.isValid() ? this._isUTC : false;
2996
}
2997

    
2998
function isUtc () {
2999
    return this.isValid() ? this._isUTC && this._offset === 0 : false;
3000
}
3001

    
3002
// ASP.NET json date format regex
3003
var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
3004

    
3005
// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
3006
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
3007
// and further modified to allow for strings containing both week and day
3008
var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
3009

    
3010
function createDuration (input, key) {
3011
    var duration = input,
3012
        // matching against regexp is expensive, do it on demand
3013
        match = null,
3014
        sign,
3015
        ret,
3016
        diffRes;
3017

    
3018
    if (isDuration(input)) {
3019
        duration = {
3020
            ms : input._milliseconds,
3021
            d  : input._days,
3022
            M  : input._months
3023
        };
3024
    } else if (isNumber(input)) {
3025
        duration = {};
3026
        if (key) {
3027
            duration[key] = input;
3028
        } else {
3029
            duration.milliseconds = input;
3030
        }
3031
    } else if (!!(match = aspNetRegex.exec(input))) {
3032
        sign = (match[1] === '-') ? -1 : 1;
3033
        duration = {
3034
            y  : 0,
3035
            d  : toInt(match[DATE])                         * sign,
3036
            h  : toInt(match[HOUR])                         * sign,
3037
            m  : toInt(match[MINUTE])                       * sign,
3038
            s  : toInt(match[SECOND])                       * sign,
3039
            ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
3040
        };
3041
    } else if (!!(match = isoRegex.exec(input))) {
3042
        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
3043
        duration = {
3044
            y : parseIso(match[2], sign),
3045
            M : parseIso(match[3], sign),
3046
            w : parseIso(match[4], sign),
3047
            d : parseIso(match[5], sign),
3048
            h : parseIso(match[6], sign),
3049
            m : parseIso(match[7], sign),
3050
            s : parseIso(match[8], sign)
3051
        };
3052
    } else if (duration == null) {// checks for null or undefined
3053
        duration = {};
3054
    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
3055
        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
3056

    
3057
        duration = {};
3058
        duration.ms = diffRes.milliseconds;
3059
        duration.M = diffRes.months;
3060
    }
3061

    
3062
    ret = new Duration(duration);
3063

    
3064
    if (isDuration(input) && hasOwnProp(input, '_locale')) {
3065
        ret._locale = input._locale;
3066
    }
3067

    
3068
    return ret;
3069
}
3070

    
3071
createDuration.fn = Duration.prototype;
3072
createDuration.invalid = createInvalid$1;
3073

    
3074
function parseIso (inp, sign) {
3075
    // We'd normally use ~~inp for this, but unfortunately it also
3076
    // converts floats to ints.
3077
    // inp may be undefined, so careful calling replace on it.
3078
    var res = inp && parseFloat(inp.replace(',', '.'));
3079
    // apply sign while we're at it
3080
    return (isNaN(res) ? 0 : res) * sign;
3081
}
3082

    
3083
function positiveMomentsDifference(base, other) {
3084
    var res = {milliseconds: 0, months: 0};
3085

    
3086
    res.months = other.month() - base.month() +
3087
        (other.year() - base.year()) * 12;
3088
    if (base.clone().add(res.months, 'M').isAfter(other)) {
3089
        --res.months;
3090
    }
3091

    
3092
    res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
3093

    
3094
    return res;
3095
}
3096

    
3097
function momentsDifference(base, other) {
3098
    var res;
3099
    if (!(base.isValid() && other.isValid())) {
3100
        return {milliseconds: 0, months: 0};
3101
    }
3102

    
3103
    other = cloneWithOffset(other, base);
3104
    if (base.isBefore(other)) {
3105
        res = positiveMomentsDifference(base, other);
3106
    } else {
3107
        res = positiveMomentsDifference(other, base);
3108
        res.milliseconds = -res.milliseconds;
3109
        res.months = -res.months;
3110
    }
3111

    
3112
    return res;
3113
}
3114

    
3115
// TODO: remove 'name' arg after deprecation is removed
3116
function createAdder(direction, name) {
3117
    return function (val, period) {
3118
        var dur, tmp;
3119
        //invert the arguments, but complain about it
3120
        if (period !== null && !isNaN(+period)) {
3121
            deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
3122
            'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
3123
            tmp = val; val = period; period = tmp;
3124
        }
3125

    
3126
        val = typeof val === 'string' ? +val : val;
3127
        dur = createDuration(val, period);
3128
        addSubtract(this, dur, direction);
3129
        return this;
3130
    };
3131
}
3132

    
3133
function addSubtract (mom, duration, isAdding, updateOffset) {
3134
    var milliseconds = duration._milliseconds,
3135
        days = absRound(duration._days),
3136
        months = absRound(duration._months);
3137

    
3138
    if (!mom.isValid()) {
3139
        // No op
3140
        return;
3141
    }
3142

    
3143
    updateOffset = updateOffset == null ? true : updateOffset;
3144

    
3145
    if (months) {
3146
        setMonth(mom, get(mom, 'Month') + months * isAdding);
3147
    }
3148
    if (days) {
3149
        set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
3150
    }
3151
    if (milliseconds) {
3152
        mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
3153
    }
3154
    if (updateOffset) {
3155
        hooks.updateOffset(mom, days || months);
3156
    }
3157
}
3158

    
3159
var add      = createAdder(1, 'add');
3160
var subtract = createAdder(-1, 'subtract');
3161

    
3162
function getCalendarFormat(myMoment, now) {
3163
    var diff = myMoment.diff(now, 'days', true);
3164
    return diff < -6 ? 'sameElse' :
3165
            diff < -1 ? 'lastWeek' :
3166
            diff < 0 ? 'lastDay' :
3167
            diff < 1 ? 'sameDay' :
3168
            diff < 2 ? 'nextDay' :
3169
            diff < 7 ? 'nextWeek' : 'sameElse';
3170
}
3171

    
3172
function calendar$1 (time, formats) {
3173
    // We want to compare the start of today, vs this.
3174
    // Getting start-of-today depends on whether we're local/utc/offset or not.
3175
    var now = time || createLocal(),
3176
        sod = cloneWithOffset(now, this).startOf('day'),
3177
        format = hooks.calendarFormat(this, sod) || 'sameElse';
3178

    
3179
    var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
3180

    
3181
    return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
3182
}
3183

    
3184
function clone () {
3185
    return new Moment(this);
3186
}
3187

    
3188
function isAfter (input, units) {
3189
    var localInput = isMoment(input) ? input : createLocal(input);
3190
    if (!(this.isValid() && localInput.isValid())) {
3191
        return false;
3192
    }
3193
    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
3194
    if (units === 'millisecond') {
3195
        return this.valueOf() > localInput.valueOf();
3196
    } else {
3197
        return localInput.valueOf() < this.clone().startOf(units).valueOf();
3198
    }
3199
}
3200

    
3201
function isBefore (input, units) {
3202
    var localInput = isMoment(input) ? input : createLocal(input);
3203
    if (!(this.isValid() && localInput.isValid())) {
3204
        return false;
3205
    }
3206
    units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
3207
    if (units === 'millisecond') {
3208
        return this.valueOf() < localInput.valueOf();
3209
    } else {
3210
        return this.clone().endOf(units).valueOf() < localInput.valueOf();
3211
    }
3212
}
3213

    
3214
function isBetween (from, to, units, inclusivity) {
3215
    inclusivity = inclusivity || '()';
3216
    return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
3217
        (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
3218
}
3219

    
3220
function isSame (input, units) {
3221
    var localInput = isMoment(input) ? input : createLocal(input),
3222
        inputMs;
3223
    if (!(this.isValid() && localInput.isValid())) {
3224
        return false;
3225
    }
3226
    units = normalizeUnits(units || 'millisecond');
3227
    if (units === 'millisecond') {
3228
        return this.valueOf() === localInput.valueOf();
3229
    } else {
3230
        inputMs = localInput.valueOf();
3231
        return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
3232
    }
3233
}
3234

    
3235
function isSameOrAfter (input, units) {
3236
    return this.isSame(input, units) || this.isAfter(input,units);
3237
}
3238

    
3239
function isSameOrBefore (input, units) {
3240
    return this.isSame(input, units) || this.isBefore(input,units);
3241
}
3242

    
3243
function diff (input, units, asFloat) {
3244
    var that,
3245
        zoneDelta,
3246
        output;
3247

    
3248
    if (!this.isValid()) {
3249
        return NaN;
3250
    }
3251

    
3252
    that = cloneWithOffset(input, this);
3253

    
3254
    if (!that.isValid()) {
3255
        return NaN;
3256
    }
3257

    
3258
    zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
3259

    
3260
    units = normalizeUnits(units);
3261

    
3262
    switch (units) {
3263
        case 'year': output = monthDiff(this, that) / 12; break;
3264
        case 'month': output = monthDiff(this, that); break;
3265
        case 'quarter': output = monthDiff(this, that) / 3; break;
3266
        case 'second': output = (this - that) / 1e3; break; // 1000
3267
        case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
3268
        case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
3269
        case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
3270
        case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
3271
        default: output = this - that;
3272
    }
3273

    
3274
    return asFloat ? output : absFloor(output);
3275
}
3276

    
3277
function monthDiff (a, b) {
3278
    // difference in months
3279
    var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
3280
        // b is in (anchor - 1 month, anchor + 1 month)
3281
        anchor = a.clone().add(wholeMonthDiff, 'months'),
3282
        anchor2, adjust;
3283

    
3284
    if (b - anchor < 0) {
3285
        anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
3286
        // linear across the month
3287
        adjust = (b - anchor) / (anchor - anchor2);
3288
    } else {
3289
        anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
3290
        // linear across the month
3291
        adjust = (b - anchor) / (anchor2 - anchor);
3292
    }
3293

    
3294
    //check for negative zero, return zero if negative zero
3295
    return -(wholeMonthDiff + adjust) || 0;
3296
}
3297

    
3298
hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
3299
hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
3300

    
3301
function toString () {
3302
    return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
3303
}
3304

    
3305
function toISOString(keepOffset) {
3306
    if (!this.isValid()) {
3307
        return null;
3308
    }
3309
    var utc = keepOffset !== true;
3310
    var m = utc ? this.clone().utc() : this;
3311
    if (m.year() < 0 || m.year() > 9999) {
3312
        return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
3313
    }
3314
    if (isFunction(Date.prototype.toISOString)) {
3315
        // native implementation is ~50x faster, use it when we can
3316
        if (utc) {
3317
            return this.toDate().toISOString();
3318
        } else {
3319
            return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z'));
3320
        }
3321
    }
3322
    return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
3323
}
3324

    
3325
/**
3326
 * Return a human readable representation of a moment that can
3327
 * also be evaluated to get a new moment which is the same
3328
 *
3329
 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
3330
 */
3331
function inspect () {
3332
    if (!this.isValid()) {
3333
        return 'moment.invalid(/* ' + this._i + ' */)';
3334
    }
3335
    var func = 'moment';
3336
    var zone = '';
3337
    if (!this.isLocal()) {
3338
        func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
3339
        zone = 'Z';
3340
    }
3341
    var prefix = '[' + func + '("]';
3342
    var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
3343
    var datetime = '-MM-DD[T]HH:mm:ss.SSS';
3344
    var suffix = zone + '[")]';
3345

    
3346
    return this.format(prefix + year + datetime + suffix);
3347
}
3348

    
3349
function format (inputString) {
3350
    if (!inputString) {
3351
        inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
3352
    }
3353
    var output = formatMoment(this, inputString);
3354
    return this.localeData().postformat(output);
3355
}
3356

    
3357
function from (time, withoutSuffix) {
3358
    if (this.isValid() &&
3359
            ((isMoment(time) && time.isValid()) ||
3360
             createLocal(time).isValid())) {
3361
        return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
3362
    } else {
3363
        return this.localeData().invalidDate();
3364
    }
3365
}
3366

    
3367
function fromNow (withoutSuffix) {
3368
    return this.from(createLocal(), withoutSuffix);
3369
}
3370

    
3371
function to (time, withoutSuffix) {
3372
    if (this.isValid() &&
3373
            ((isMoment(time) && time.isValid()) ||
3374
             createLocal(time).isValid())) {
3375
        return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
3376
    } else {
3377
        return this.localeData().invalidDate();
3378
    }
3379
}
3380

    
3381
function toNow (withoutSuffix) {
3382
    return this.to(createLocal(), withoutSuffix);
3383
}
3384

    
3385
// If passed a locale key, it will set the locale for this
3386
// instance.  Otherwise, it will return the locale configuration
3387
// variables for this instance.
3388
function locale (key) {
3389
    var newLocaleData;
3390

    
3391
    if (key === undefined) {
3392
        return this._locale._abbr;
3393
    } else {
3394
        newLocaleData = getLocale(key);
3395
        if (newLocaleData != null) {
3396
            this._locale = newLocaleData;
3397
        }
3398
        return this;
3399
    }
3400
}
3401

    
3402
var lang = deprecate(
3403
    'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
3404
    function (key) {
3405
        if (key === undefined) {
3406
            return this.localeData();
3407
        } else {
3408
            return this.locale(key);
3409
        }
3410
    }
3411
);
3412

    
3413
function localeData () {
3414
    return this._locale;
3415
}
3416

    
3417
function startOf (units) {
3418
    units = normalizeUnits(units);
3419
    // the following switch intentionally omits break keywords
3420
    // to utilize falling through the cases.
3421
    switch (units) {
3422
        case 'year':
3423
            this.month(0);
3424
            /* falls through */
3425
        case 'quarter':
3426
        case 'month':
3427
            this.date(1);
3428
            /* falls through */
3429
        case 'week':
3430
        case 'isoWeek':
3431
        case 'day':
3432
        case 'date':
3433
            this.hours(0);
3434
            /* falls through */
3435
        case 'hour':
3436
            this.minutes(0);
3437
            /* falls through */
3438
        case 'minute':
3439
            this.seconds(0);
3440
            /* falls through */
3441
        case 'second':
3442
            this.milliseconds(0);
3443
    }
3444

    
3445
    // weeks are a special case
3446
    if (units === 'week') {
3447
        this.weekday(0);
3448
    }
3449
    if (units === 'isoWeek') {
3450
        this.isoWeekday(1);
3451
    }
3452

    
3453
    // quarters are also special
3454
    if (units === 'quarter') {
3455
        this.month(Math.floor(this.month() / 3) * 3);
3456
    }
3457

    
3458
    return this;
3459
}
3460

    
3461
function endOf (units) {
3462
    units = normalizeUnits(units);
3463
    if (units === undefined || units === 'millisecond') {
3464
        return this;
3465
    }
3466

    
3467
    // 'date' is an alias for 'day', so it should be considered as such.
3468
    if (units === 'date') {
3469
        units = 'day';
3470
    }
3471

    
3472
    return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
3473
}
3474

    
3475
function valueOf () {
3476
    return this._d.valueOf() - ((this._offset || 0) * 60000);
3477
}
3478

    
3479
function unix () {
3480
    return Math.floor(this.valueOf() / 1000);
3481
}
3482

    
3483
function toDate () {
3484
    return new Date(this.valueOf());
3485
}
3486

    
3487
function toArray () {
3488
    var m = this;
3489
    return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
3490
}
3491

    
3492
function toObject () {
3493
    var m = this;
3494
    return {
3495
        years: m.year(),
3496
        months: m.month(),
3497
        date: m.date(),
3498
        hours: m.hours(),
3499
        minutes: m.minutes(),
3500
        seconds: m.seconds(),
3501
        milliseconds: m.milliseconds()
3502
    };
3503
}
3504

    
3505
function toJSON () {
3506
    // new Date(NaN).toJSON() === null
3507
    return this.isValid() ? this.toISOString() : null;
3508
}
3509

    
3510
function isValid$2 () {
3511
    return isValid(this);
3512
}
3513

    
3514
function parsingFlags () {
3515
    return extend({}, getParsingFlags(this));
3516
}
3517

    
3518
function invalidAt () {
3519
    return getParsingFlags(this).overflow;
3520
}
3521

    
3522
function creationData() {
3523
    return {
3524
        input: this._i,
3525
        format: this._f,
3526
        locale: this._locale,
3527
        isUTC: this._isUTC,
3528
        strict: this._strict
3529
    };
3530
}
3531

    
3532
// FORMATTING
3533

    
3534
addFormatToken(0, ['gg', 2], 0, function () {
3535
    return this.weekYear() % 100;
3536
});
3537

    
3538
addFormatToken(0, ['GG', 2], 0, function () {
3539
    return this.isoWeekYear() % 100;
3540
});
3541

    
3542
function addWeekYearFormatToken (token, getter) {
3543
    addFormatToken(0, [token, token.length], 0, getter);
3544
}
3545

    
3546
addWeekYearFormatToken('gggg',     'weekYear');
3547
addWeekYearFormatToken('ggggg',    'weekYear');
3548
addWeekYearFormatToken('GGGG',  'isoWeekYear');
3549
addWeekYearFormatToken('GGGGG', 'isoWeekYear');
3550

    
3551
// ALIASES
3552

    
3553
addUnitAlias('weekYear', 'gg');
3554
addUnitAlias('isoWeekYear', 'GG');
3555

    
3556
// PRIORITY
3557

    
3558
addUnitPriority('weekYear', 1);
3559
addUnitPriority('isoWeekYear', 1);
3560

    
3561

    
3562
// PARSING
3563

    
3564
addRegexToken('G',      matchSigned);
3565
addRegexToken('g',      matchSigned);
3566
addRegexToken('GG',     match1to2, match2);
3567
addRegexToken('gg',     match1to2, match2);
3568
addRegexToken('GGGG',   match1to4, match4);
3569
addRegexToken('gggg',   match1to4, match4);
3570
addRegexToken('GGGGG',  match1to6, match6);
3571
addRegexToken('ggggg',  match1to6, match6);
3572

    
3573
addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
3574
    week[token.substr(0, 2)] = toInt(input);
3575
});
3576

    
3577
addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
3578
    week[token] = hooks.parseTwoDigitYear(input);
3579
});
3580

    
3581
// MOMENTS
3582

    
3583
function getSetWeekYear (input) {
3584
    return getSetWeekYearHelper.call(this,
3585
            input,
3586
            this.week(),
3587
            this.weekday(),
3588
            this.localeData()._week.dow,
3589
            this.localeData()._week.doy);
3590
}
3591

    
3592
function getSetISOWeekYear (input) {
3593
    return getSetWeekYearHelper.call(this,
3594
            input, this.isoWeek(), this.isoWeekday(), 1, 4);
3595
}
3596

    
3597
function getISOWeeksInYear () {
3598
    return weeksInYear(this.year(), 1, 4);
3599
}
3600

    
3601
function getWeeksInYear () {
3602
    var weekInfo = this.localeData()._week;
3603
    return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
3604
}
3605

    
3606
function getSetWeekYearHelper(input, week, weekday, dow, doy) {
3607
    var weeksTarget;
3608
    if (input == null) {
3609
        return weekOfYear(this, dow, doy).year;
3610
    } else {
3611
        weeksTarget = weeksInYear(input, dow, doy);
3612
        if (week > weeksTarget) {
3613
            week = weeksTarget;
3614
        }
3615
        return setWeekAll.call(this, input, week, weekday, dow, doy);
3616
    }
3617
}
3618

    
3619
function setWeekAll(weekYear, week, weekday, dow, doy) {
3620
    var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
3621
        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
3622

    
3623
    this.year(date.getUTCFullYear());
3624
    this.month(date.getUTCMonth());
3625
    this.date(date.getUTCDate());
3626
    return this;
3627
}
3628

    
3629
// FORMATTING
3630

    
3631
addFormatToken('Q', 0, 'Qo', 'quarter');
3632

    
3633
// ALIASES
3634

    
3635
addUnitAlias('quarter', 'Q');
3636

    
3637
// PRIORITY
3638

    
3639
addUnitPriority('quarter', 7);
3640

    
3641
// PARSING
3642

    
3643
addRegexToken('Q', match1);
3644
addParseToken('Q', function (input, array) {
3645
    array[MONTH] = (toInt(input) - 1) * 3;
3646
});
3647

    
3648
// MOMENTS
3649

    
3650
function getSetQuarter (input) {
3651
    return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
3652
}
3653

    
3654
// FORMATTING
3655

    
3656
addFormatToken('D', ['DD', 2], 'Do', 'date');
3657

    
3658
// ALIASES
3659

    
3660
addUnitAlias('date', 'D');
3661

    
3662
// PRIOROITY
3663
addUnitPriority('date', 9);
3664

    
3665
// PARSING
3666

    
3667
addRegexToken('D',  match1to2);
3668
addRegexToken('DD', match1to2, match2);
3669
addRegexToken('Do', function (isStrict, locale) {
3670
    // TODO: Remove "ordinalParse" fallback in next major release.
3671
    return isStrict ?
3672
      (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
3673
      locale._dayOfMonthOrdinalParseLenient;
3674
});
3675

    
3676
addParseToken(['D', 'DD'], DATE);
3677
addParseToken('Do', function (input, array) {
3678
    array[DATE] = toInt(input.match(match1to2)[0]);
3679
});
3680

    
3681
// MOMENTS
3682

    
3683
var getSetDayOfMonth = makeGetSet('Date', true);
3684

    
3685
// FORMATTING
3686

    
3687
addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
3688

    
3689
// ALIASES
3690

    
3691
addUnitAlias('dayOfYear', 'DDD');
3692

    
3693
// PRIORITY
3694
addUnitPriority('dayOfYear', 4);
3695

    
3696
// PARSING
3697

    
3698
addRegexToken('DDD',  match1to3);
3699
addRegexToken('DDDD', match3);
3700
addParseToken(['DDD', 'DDDD'], function (input, array, config) {
3701
    config._dayOfYear = toInt(input);
3702
});
3703

    
3704
// HELPERS
3705

    
3706
// MOMENTS
3707

    
3708
function getSetDayOfYear (input) {
3709
    var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
3710
    return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
3711
}
3712

    
3713
// FORMATTING
3714

    
3715
addFormatToken('m', ['mm', 2], 0, 'minute');
3716

    
3717
// ALIASES
3718

    
3719
addUnitAlias('minute', 'm');
3720

    
3721
// PRIORITY
3722

    
3723
addUnitPriority('minute', 14);
3724

    
3725
// PARSING
3726

    
3727
addRegexToken('m',  match1to2);
3728
addRegexToken('mm', match1to2, match2);
3729
addParseToken(['m', 'mm'], MINUTE);
3730

    
3731
// MOMENTS
3732

    
3733
var getSetMinute = makeGetSet('Minutes', false);
3734

    
3735
// FORMATTING
3736

    
3737
addFormatToken('s', ['ss', 2], 0, 'second');
3738

    
3739
// ALIASES
3740

    
3741
addUnitAlias('second', 's');
3742

    
3743
// PRIORITY
3744

    
3745
addUnitPriority('second', 15);
3746

    
3747
// PARSING
3748

    
3749
addRegexToken('s',  match1to2);
3750
addRegexToken('ss', match1to2, match2);
3751
addParseToken(['s', 'ss'], SECOND);
3752

    
3753
// MOMENTS
3754

    
3755
var getSetSecond = makeGetSet('Seconds', false);
3756

    
3757
// FORMATTING
3758

    
3759
addFormatToken('S', 0, 0, function () {
3760
    return ~~(this.millisecond() / 100);
3761
});
3762

    
3763
addFormatToken(0, ['SS', 2], 0, function () {
3764
    return ~~(this.millisecond() / 10);
3765
});
3766

    
3767
addFormatToken(0, ['SSS', 3], 0, 'millisecond');
3768
addFormatToken(0, ['SSSS', 4], 0, function () {
3769
    return this.millisecond() * 10;
3770
});
3771
addFormatToken(0, ['SSSSS', 5], 0, function () {
3772
    return this.millisecond() * 100;
3773
});
3774
addFormatToken(0, ['SSSSSS', 6], 0, function () {
3775
    return this.millisecond() * 1000;
3776
});
3777
addFormatToken(0, ['SSSSSSS', 7], 0, function () {
3778
    return this.millisecond() * 10000;
3779
});
3780
addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
3781
    return this.millisecond() * 100000;
3782
});
3783
addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
3784
    return this.millisecond() * 1000000;
3785
});
3786

    
3787

    
3788
// ALIASES
3789

    
3790
addUnitAlias('millisecond', 'ms');
3791

    
3792
// PRIORITY
3793

    
3794
addUnitPriority('millisecond', 16);
3795

    
3796
// PARSING
3797

    
3798
addRegexToken('S',    match1to3, match1);
3799
addRegexToken('SS',   match1to3, match2);
3800
addRegexToken('SSS',  match1to3, match3);
3801

    
3802
var token;
3803
for (token = 'SSSS'; token.length <= 9; token += 'S') {
3804
    addRegexToken(token, matchUnsigned);
3805
}
3806

    
3807
function parseMs(input, array) {
3808
    array[MILLISECOND] = toInt(('0.' + input) * 1000);
3809
}
3810

    
3811
for (token = 'S'; token.length <= 9; token += 'S') {
3812
    addParseToken(token, parseMs);
3813
}
3814
// MOMENTS
3815

    
3816
var getSetMillisecond = makeGetSet('Milliseconds', false);
3817

    
3818
// FORMATTING
3819

    
3820
addFormatToken('z',  0, 0, 'zoneAbbr');
3821
addFormatToken('zz', 0, 0, 'zoneName');
3822

    
3823
// MOMENTS
3824

    
3825
function getZoneAbbr () {
3826
    return this._isUTC ? 'UTC' : '';
3827
}
3828

    
3829
function getZoneName () {
3830
    return this._isUTC ? 'Coordinated Universal Time' : '';
3831
}
3832

    
3833
var proto = Moment.prototype;
3834

    
3835
proto.add               = add;
3836
proto.calendar          = calendar$1;
3837
proto.clone             = clone;
3838
proto.diff              = diff;
3839
proto.endOf             = endOf;
3840
proto.format            = format;
3841
proto.from              = from;
3842
proto.fromNow           = fromNow;
3843
proto.to                = to;
3844
proto.toNow             = toNow;
3845
proto.get               = stringGet;
3846
proto.invalidAt         = invalidAt;
3847
proto.isAfter           = isAfter;
3848
proto.isBefore          = isBefore;
3849
proto.isBetween         = isBetween;
3850
proto.isSame            = isSame;
3851
proto.isSameOrAfter     = isSameOrAfter;
3852
proto.isSameOrBefore    = isSameOrBefore;
3853
proto.isValid           = isValid$2;
3854
proto.lang              = lang;
3855
proto.locale            = locale;
3856
proto.localeData        = localeData;
3857
proto.max               = prototypeMax;
3858
proto.min               = prototypeMin;
3859
proto.parsingFlags      = parsingFlags;
3860
proto.set               = stringSet;
3861
proto.startOf           = startOf;
3862
proto.subtract          = subtract;
3863
proto.toArray           = toArray;
3864
proto.toObject          = toObject;
3865
proto.toDate            = toDate;
3866
proto.toISOString       = toISOString;
3867
proto.inspect           = inspect;
3868
proto.toJSON            = toJSON;
3869
proto.toString          = toString;
3870
proto.unix              = unix;
3871
proto.valueOf           = valueOf;
3872
proto.creationData      = creationData;
3873
proto.year       = getSetYear;
3874
proto.isLeapYear = getIsLeapYear;
3875
proto.weekYear    = getSetWeekYear;
3876
proto.isoWeekYear = getSetISOWeekYear;
3877
proto.quarter = proto.quarters = getSetQuarter;
3878
proto.month       = getSetMonth;
3879
proto.daysInMonth = getDaysInMonth;
3880
proto.week           = proto.weeks        = getSetWeek;
3881
proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
3882
proto.weeksInYear    = getWeeksInYear;
3883
proto.isoWeeksInYear = getISOWeeksInYear;
3884
proto.date       = getSetDayOfMonth;
3885
proto.day        = proto.days             = getSetDayOfWeek;
3886
proto.weekday    = getSetLocaleDayOfWeek;
3887
proto.isoWeekday = getSetISODayOfWeek;
3888
proto.dayOfYear  = getSetDayOfYear;
3889
proto.hour = proto.hours = getSetHour;
3890
proto.minute = proto.minutes = getSetMinute;
3891
proto.second = proto.seconds = getSetSecond;
3892
proto.millisecond = proto.milliseconds = getSetMillisecond;
3893
proto.utcOffset            = getSetOffset;
3894
proto.utc                  = setOffsetToUTC;
3895
proto.local                = setOffsetToLocal;
3896
proto.parseZone            = setOffsetToParsedOffset;
3897
proto.hasAlignedHourOffset = hasAlignedHourOffset;
3898
proto.isDST                = isDaylightSavingTime;
3899
proto.isLocal              = isLocal;
3900
proto.isUtcOffset          = isUtcOffset;
3901
proto.isUtc                = isUtc;
3902
proto.isUTC                = isUtc;
3903
proto.zoneAbbr = getZoneAbbr;
3904
proto.zoneName = getZoneName;
3905
proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
3906
proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
3907
proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
3908
proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
3909
proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
3910

    
3911
function createUnix (input) {
3912
    return createLocal(input * 1000);
3913
}
3914

    
3915
function createInZone () {
3916
    return createLocal.apply(null, arguments).parseZone();
3917
}
3918

    
3919
function preParsePostFormat (string) {
3920
    return string;
3921
}
3922

    
3923
var proto$1 = Locale.prototype;
3924

    
3925
proto$1.calendar        = calendar;
3926
proto$1.longDateFormat  = longDateFormat;
3927
proto$1.invalidDate     = invalidDate;
3928
proto$1.ordinal         = ordinal;
3929
proto$1.preparse        = preParsePostFormat;
3930
proto$1.postformat      = preParsePostFormat;
3931
proto$1.relativeTime    = relativeTime;
3932
proto$1.pastFuture      = pastFuture;
3933
proto$1.set             = set;
3934

    
3935
proto$1.months            =        localeMonths;
3936
proto$1.monthsShort       =        localeMonthsShort;
3937
proto$1.monthsParse       =        localeMonthsParse;
3938
proto$1.monthsRegex       = monthsRegex;
3939
proto$1.monthsShortRegex  = monthsShortRegex;
3940
proto$1.week = localeWeek;
3941
proto$1.firstDayOfYear = localeFirstDayOfYear;
3942
proto$1.firstDayOfWeek = localeFirstDayOfWeek;
3943

    
3944
proto$1.weekdays       =        localeWeekdays;
3945
proto$1.weekdaysMin    =        localeWeekdaysMin;
3946
proto$1.weekdaysShort  =        localeWeekdaysShort;
3947
proto$1.weekdaysParse  =        localeWeekdaysParse;
3948

    
3949
proto$1.weekdaysRegex       =        weekdaysRegex;
3950
proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
3951
proto$1.weekdaysMinRegex    =        weekdaysMinRegex;
3952

    
3953
proto$1.isPM = localeIsPM;
3954
proto$1.meridiem = localeMeridiem;
3955

    
3956
function get$1 (format, index, field, setter) {
3957
    var locale = getLocale();
3958
    var utc = createUTC().set(setter, index);
3959
    return locale[field](utc, format);
3960
}
3961

    
3962
function listMonthsImpl (format, index, field) {
3963
    if (isNumber(format)) {
3964
        index = format;
3965
        format = undefined;
3966
    }
3967

    
3968
    format = format || '';
3969

    
3970
    if (index != null) {
3971
        return get$1(format, index, field, 'month');
3972
    }
3973

    
3974
    var i;
3975
    var out = [];
3976
    for (i = 0; i < 12; i++) {
3977
        out[i] = get$1(format, i, field, 'month');
3978
    }
3979
    return out;
3980
}
3981

    
3982
// ()
3983
// (5)
3984
// (fmt, 5)
3985
// (fmt)
3986
// (true)
3987
// (true, 5)
3988
// (true, fmt, 5)
3989
// (true, fmt)
3990
function listWeekdaysImpl (localeSorted, format, index, field) {
3991
    if (typeof localeSorted === 'boolean') {
3992
        if (isNumber(format)) {
3993
            index = format;
3994
            format = undefined;
3995
        }
3996

    
3997
        format = format || '';
3998
    } else {
3999
        format = localeSorted;
4000
        index = format;
4001
        localeSorted = false;
4002

    
4003
        if (isNumber(format)) {
4004
            index = format;
4005
            format = undefined;
4006
        }
4007

    
4008
        format = format || '';
4009
    }
4010

    
4011
    var locale = getLocale(),
4012
        shift = localeSorted ? locale._week.dow : 0;
4013

    
4014
    if (index != null) {
4015
        return get$1(format, (index + shift) % 7, field, 'day');
4016
    }
4017

    
4018
    var i;
4019
    var out = [];
4020
    for (i = 0; i < 7; i++) {
4021
        out[i] = get$1(format, (i + shift) % 7, field, 'day');
4022
    }
4023
    return out;
4024
}
4025

    
4026
function listMonths (format, index) {
4027
    return listMonthsImpl(format, index, 'months');
4028
}
4029

    
4030
function listMonthsShort (format, index) {
4031
    return listMonthsImpl(format, index, 'monthsShort');
4032
}
4033

    
4034
function listWeekdays (localeSorted, format, index) {
4035
    return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
4036
}
4037

    
4038
function listWeekdaysShort (localeSorted, format, index) {
4039
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
4040
}
4041

    
4042
function listWeekdaysMin (localeSorted, format, index) {
4043
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
4044
}
4045

    
4046
getSetGlobalLocale('en', {
4047
    dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
4048
    ordinal : function (number) {
4049
        var b = number % 10,
4050
            output = (toInt(number % 100 / 10) === 1) ? 'th' :
4051
            (b === 1) ? 'st' :
4052
            (b === 2) ? 'nd' :
4053
            (b === 3) ? 'rd' : 'th';
4054
        return number + output;
4055
    }
4056
});
4057

    
4058
// Side effect imports
4059

    
4060
hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
4061
hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
4062

    
4063
var mathAbs = Math.abs;
4064

    
4065
function abs () {
4066
    var data           = this._data;
4067

    
4068
    this._milliseconds = mathAbs(this._milliseconds);
4069
    this._days         = mathAbs(this._days);
4070
    this._months       = mathAbs(this._months);
4071

    
4072
    data.milliseconds  = mathAbs(data.milliseconds);
4073
    data.seconds       = mathAbs(data.seconds);
4074
    data.minutes       = mathAbs(data.minutes);
4075
    data.hours         = mathAbs(data.hours);
4076
    data.months        = mathAbs(data.months);
4077
    data.years         = mathAbs(data.years);
4078

    
4079
    return this;
4080
}
4081

    
4082
function addSubtract$1 (duration, input, value, direction) {
4083
    var other = createDuration(input, value);
4084

    
4085
    duration._milliseconds += direction * other._milliseconds;
4086
    duration._days         += direction * other._days;
4087
    duration._months       += direction * other._months;
4088

    
4089
    return duration._bubble();
4090
}
4091

    
4092
// supports only 2.0-style add(1, 's') or add(duration)
4093
function add$1 (input, value) {
4094
    return addSubtract$1(this, input, value, 1);
4095
}
4096

    
4097
// supports only 2.0-style subtract(1, 's') or subtract(duration)
4098
function subtract$1 (input, value) {
4099
    return addSubtract$1(this, input, value, -1);
4100
}
4101

    
4102
function absCeil (number) {
4103
    if (number < 0) {
4104
        return Math.floor(number);
4105
    } else {
4106
        return Math.ceil(number);
4107
    }
4108
}
4109

    
4110
function bubble () {
4111
    var milliseconds = this._milliseconds;
4112
    var days         = this._days;
4113
    var months       = this._months;
4114
    var data         = this._data;
4115
    var seconds, minutes, hours, years, monthsFromDays;
4116

    
4117
    // if we have a mix of positive and negative values, bubble down first
4118
    // check: https://github.com/moment/moment/issues/2166
4119
    if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
4120
            (milliseconds <= 0 && days <= 0 && months <= 0))) {
4121
        milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
4122
        days = 0;
4123
        months = 0;
4124
    }
4125

    
4126
    // The following code bubbles up values, see the tests for
4127
    // examples of what that means.
4128
    data.milliseconds = milliseconds % 1000;
4129

    
4130
    seconds           = absFloor(milliseconds / 1000);
4131
    data.seconds      = seconds % 60;
4132

    
4133
    minutes           = absFloor(seconds / 60);
4134
    data.minutes      = minutes % 60;
4135

    
4136
    hours             = absFloor(minutes / 60);
4137
    data.hours        = hours % 24;
4138

    
4139
    days += absFloor(hours / 24);
4140

    
4141
    // convert days to months
4142
    monthsFromDays = absFloor(daysToMonths(days));
4143
    months += monthsFromDays;
4144
    days -= absCeil(monthsToDays(monthsFromDays));
4145

    
4146
    // 12 months -> 1 year
4147
    years = absFloor(months / 12);
4148
    months %= 12;
4149

    
4150
    data.days   = days;
4151
    data.months = months;
4152
    data.years  = years;
4153

    
4154
    return this;
4155
}
4156

    
4157
function daysToMonths (days) {
4158
    // 400 years have 146097 days (taking into account leap year rules)
4159
    // 400 years have 12 months === 4800
4160
    return days * 4800 / 146097;
4161
}
4162

    
4163
function monthsToDays (months) {
4164
    // the reverse of daysToMonths
4165
    return months * 146097 / 4800;
4166
}
4167

    
4168
function as (units) {
4169
    if (!this.isValid()) {
4170
        return NaN;
4171
    }
4172
    var days;
4173
    var months;
4174
    var milliseconds = this._milliseconds;
4175

    
4176
    units = normalizeUnits(units);
4177

    
4178
    if (units === 'month' || units === 'year') {
4179
        days   = this._days   + milliseconds / 864e5;
4180
        months = this._months + daysToMonths(days);
4181
        return units === 'month' ? months : months / 12;
4182
    } else {
4183
        // handle milliseconds separately because of floating point math errors (issue #1867)
4184
        days = this._days + Math.round(monthsToDays(this._months));
4185
        switch (units) {
4186
            case 'week'   : return days / 7     + milliseconds / 6048e5;
4187
            case 'day'    : return days         + milliseconds / 864e5;
4188
            case 'hour'   : return days * 24    + milliseconds / 36e5;
4189
            case 'minute' : return days * 1440  + milliseconds / 6e4;
4190
            case 'second' : return days * 86400 + milliseconds / 1000;
4191
            // Math.floor prevents floating point math errors here
4192
            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
4193
            default: throw new Error('Unknown unit ' + units);
4194
        }
4195
    }
4196
}
4197

    
4198
// TODO: Use this.as('ms')?
4199
function valueOf$1 () {
4200
    if (!this.isValid()) {
4201
        return NaN;
4202
    }
4203
    return (
4204
        this._milliseconds +
4205
        this._days * 864e5 +
4206
        (this._months % 12) * 2592e6 +
4207
        toInt(this._months / 12) * 31536e6
4208
    );
4209
}
4210

    
4211
function makeAs (alias) {
4212
    return function () {
4213
        return this.as(alias);
4214
    };
4215
}
4216

    
4217
var asMilliseconds = makeAs('ms');
4218
var asSeconds      = makeAs('s');
4219
var asMinutes      = makeAs('m');
4220
var asHours        = makeAs('h');
4221
var asDays         = makeAs('d');
4222
var asWeeks        = makeAs('w');
4223
var asMonths       = makeAs('M');
4224
var asYears        = makeAs('y');
4225

    
4226
function clone$1 () {
4227
    return createDuration(this);
4228
}
4229

    
4230
function get$2 (units) {
4231
    units = normalizeUnits(units);
4232
    return this.isValid() ? this[units + 's']() : NaN;
4233
}
4234

    
4235
function makeGetter(name) {
4236
    return function () {
4237
        return this.isValid() ? this._data[name] : NaN;
4238
    };
4239
}
4240

    
4241
var milliseconds = makeGetter('milliseconds');
4242
var seconds      = makeGetter('seconds');
4243
var minutes      = makeGetter('minutes');
4244
var hours        = makeGetter('hours');
4245
var days         = makeGetter('days');
4246
var months       = makeGetter('months');
4247
var years        = makeGetter('years');
4248

    
4249
function weeks () {
4250
    return absFloor(this.days() / 7);
4251
}
4252

    
4253
var round = Math.round;
4254
var thresholds = {
4255
    ss: 44,         // a few seconds to seconds
4256
    s : 45,         // seconds to minute
4257
    m : 45,         // minutes to hour
4258
    h : 22,         // hours to day
4259
    d : 26,         // days to month
4260
    M : 11          // months to year
4261
};
4262

    
4263
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
4264
function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
4265
    return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
4266
}
4267

    
4268
function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
4269
    var duration = createDuration(posNegDuration).abs();
4270
    var seconds  = round(duration.as('s'));
4271
    var minutes  = round(duration.as('m'));
4272
    var hours    = round(duration.as('h'));
4273
    var days     = round(duration.as('d'));
4274
    var months   = round(duration.as('M'));
4275
    var years    = round(duration.as('y'));
4276

    
4277
    var a = seconds <= thresholds.ss && ['s', seconds]  ||
4278
            seconds < thresholds.s   && ['ss', seconds] ||
4279
            minutes <= 1             && ['m']           ||
4280
            minutes < thresholds.m   && ['mm', minutes] ||
4281
            hours   <= 1             && ['h']           ||
4282
            hours   < thresholds.h   && ['hh', hours]   ||
4283
            days    <= 1             && ['d']           ||
4284
            days    < thresholds.d   && ['dd', days]    ||
4285
            months  <= 1             && ['M']           ||
4286
            months  < thresholds.M   && ['MM', months]  ||
4287
            years   <= 1             && ['y']           || ['yy', years];
4288

    
4289
    a[2] = withoutSuffix;
4290
    a[3] = +posNegDuration > 0;
4291
    a[4] = locale;
4292
    return substituteTimeAgo.apply(null, a);
4293
}
4294

    
4295
// This function allows you to set the rounding function for relative time strings
4296
function getSetRelativeTimeRounding (roundingFunction) {
4297
    if (roundingFunction === undefined) {
4298
        return round;
4299
    }
4300
    if (typeof(roundingFunction) === 'function') {
4301
        round = roundingFunction;
4302
        return true;
4303
    }
4304
    return false;
4305
}
4306

    
4307
// This function allows you to set a threshold for relative time strings
4308
function getSetRelativeTimeThreshold (threshold, limit) {
4309
    if (thresholds[threshold] === undefined) {
4310
        return false;
4311
    }
4312
    if (limit === undefined) {
4313
        return thresholds[threshold];
4314
    }
4315
    thresholds[threshold] = limit;
4316
    if (threshold === 's') {
4317
        thresholds.ss = limit - 1;
4318
    }
4319
    return true;
4320
}
4321

    
4322
function humanize (withSuffix) {
4323
    if (!this.isValid()) {
4324
        return this.localeData().invalidDate();
4325
    }
4326

    
4327
    var locale = this.localeData();
4328
    var output = relativeTime$1(this, !withSuffix, locale);
4329

    
4330
    if (withSuffix) {
4331
        output = locale.pastFuture(+this, output);
4332
    }
4333

    
4334
    return locale.postformat(output);
4335
}
4336

    
4337
var abs$1 = Math.abs;
4338

    
4339
function sign(x) {
4340
    return ((x > 0) - (x < 0)) || +x;
4341
}
4342

    
4343
function toISOString$1() {
4344
    // for ISO strings we do not use the normal bubbling rules:
4345
    //  * milliseconds bubble up until they become hours
4346
    //  * days do not bubble at all
4347
    //  * months bubble up until they become years
4348
    // This is because there is no context-free conversion between hours and days
4349
    // (think of clock changes)
4350
    // and also not between days and months (28-31 days per month)
4351
    if (!this.isValid()) {
4352
        return this.localeData().invalidDate();
4353
    }
4354

    
4355
    var seconds = abs$1(this._milliseconds) / 1000;
4356
    var days         = abs$1(this._days);
4357
    var months       = abs$1(this._months);
4358
    var minutes, hours, years;
4359

    
4360
    // 3600 seconds -> 60 minutes -> 1 hour
4361
    minutes           = absFloor(seconds / 60);
4362
    hours             = absFloor(minutes / 60);
4363
    seconds %= 60;
4364
    minutes %= 60;
4365

    
4366
    // 12 months -> 1 year
4367
    years  = absFloor(months / 12);
4368
    months %= 12;
4369

    
4370

    
4371
    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
4372
    var Y = years;
4373
    var M = months;
4374
    var D = days;
4375
    var h = hours;
4376
    var m = minutes;
4377
    var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
4378
    var total = this.asSeconds();
4379

    
4380
    if (!total) {
4381
        // this is the same as C#'s (Noda) and python (isodate)...
4382
        // but not other JS (goog.date)
4383
        return 'P0D';
4384
    }
4385

    
4386
    var totalSign = total < 0 ? '-' : '';
4387
    var ymSign = sign(this._months) !== sign(total) ? '-' : '';
4388
    var daysSign = sign(this._days) !== sign(total) ? '-' : '';
4389
    var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
4390

    
4391
    return totalSign + 'P' +
4392
        (Y ? ymSign + Y + 'Y' : '') +
4393
        (M ? ymSign + M + 'M' : '') +
4394
        (D ? daysSign + D + 'D' : '') +
4395
        ((h || m || s) ? 'T' : '') +
4396
        (h ? hmsSign + h + 'H' : '') +
4397
        (m ? hmsSign + m + 'M' : '') +
4398
        (s ? hmsSign + s + 'S' : '');
4399
}
4400

    
4401
var proto$2 = Duration.prototype;
4402

    
4403
proto$2.isValid        = isValid$1;
4404
proto$2.abs            = abs;
4405
proto$2.add            = add$1;
4406
proto$2.subtract       = subtract$1;
4407
proto$2.as             = as;
4408
proto$2.asMilliseconds = asMilliseconds;
4409
proto$2.asSeconds      = asSeconds;
4410
proto$2.asMinutes      = asMinutes;
4411
proto$2.asHours        = asHours;
4412
proto$2.asDays         = asDays;
4413
proto$2.asWeeks        = asWeeks;
4414
proto$2.asMonths       = asMonths;
4415
proto$2.asYears        = asYears;
4416
proto$2.valueOf        = valueOf$1;
4417
proto$2._bubble        = bubble;
4418
proto$2.clone          = clone$1;
4419
proto$2.get            = get$2;
4420
proto$2.milliseconds   = milliseconds;
4421
proto$2.seconds        = seconds;
4422
proto$2.minutes        = minutes;
4423
proto$2.hours          = hours;
4424
proto$2.days           = days;
4425
proto$2.weeks          = weeks;
4426
proto$2.months         = months;
4427
proto$2.years          = years;
4428
proto$2.humanize       = humanize;
4429
proto$2.toISOString    = toISOString$1;
4430
proto$2.toString       = toISOString$1;
4431
proto$2.toJSON         = toISOString$1;
4432
proto$2.locale         = locale;
4433
proto$2.localeData     = localeData;
4434

    
4435
proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
4436
proto$2.lang = lang;
4437

    
4438
// Side effect imports
4439

    
4440
// FORMATTING
4441

    
4442
addFormatToken('X', 0, 0, 'unix');
4443
addFormatToken('x', 0, 0, 'valueOf');
4444

    
4445
// PARSING
4446

    
4447
addRegexToken('x', matchSigned);
4448
addRegexToken('X', matchTimestamp);
4449
addParseToken('X', function (input, array, config) {
4450
    config._d = new Date(parseFloat(input, 10) * 1000);
4451
});
4452
addParseToken('x', function (input, array, config) {
4453
    config._d = new Date(toInt(input));
4454
});
4455

    
4456
// Side effect imports
4457

    
4458

    
4459
hooks.version = '2.21.0';
4460

    
4461
setHookCallback(createLocal);
4462

    
4463
hooks.fn                    = proto;
4464
hooks.min                   = min;
4465
hooks.max                   = max;
4466
hooks.now                   = now;
4467
hooks.utc                   = createUTC;
4468
hooks.unix                  = createUnix;
4469
hooks.months                = listMonths;
4470
hooks.isDate                = isDate;
4471
hooks.locale                = getSetGlobalLocale;
4472
hooks.invalid               = createInvalid;
4473
hooks.duration              = createDuration;
4474
hooks.isMoment              = isMoment;
4475
hooks.weekdays              = listWeekdays;
4476
hooks.parseZone             = createInZone;
4477
hooks.localeData            = getLocale;
4478
hooks.isDuration            = isDuration;
4479
hooks.monthsShort           = listMonthsShort;
4480
hooks.weekdaysMin           = listWeekdaysMin;
4481
hooks.defineLocale          = defineLocale;
4482
hooks.updateLocale          = updateLocale;
4483
hooks.locales               = listLocales;
4484
hooks.weekdaysShort         = listWeekdaysShort;
4485
hooks.normalizeUnits        = normalizeUnits;
4486
hooks.relativeTimeRounding  = getSetRelativeTimeRounding;
4487
hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
4488
hooks.calendarFormat        = getCalendarFormat;
4489
hooks.prototype             = proto;
4490

    
4491
// currently HTML5 input type only supports 24-hour formats
4492
hooks.HTML5_FMT = {
4493
    DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm',             // <input type="datetime-local" />
4494
    DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss',  // <input type="datetime-local" step="1" />
4495
    DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS',   // <input type="datetime-local" step="0.001" />
4496
    DATE: 'YYYY-MM-DD',                             // <input type="date" />
4497
    TIME: 'HH:mm',                                  // <input type="time" />
4498
    TIME_SECONDS: 'HH:mm:ss',                       // <input type="time" step="1" />
4499
    TIME_MS: 'HH:mm:ss.SSS',                        // <input type="time" step="0.001" />
4500
    WEEK: 'YYYY-[W]WW',                             // <input type="week" />
4501
    MONTH: 'YYYY-MM'                                // <input type="month" />
4502
};
4503

    
4504
return hooks;
4505

    
4506
})));