프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / MarkusLogview / MARKUS_LOGVIEW / Scripts / moment.js @ c854511f

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

1
//! moment.js
2
//! version : 2.19.4
3
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4
//! license : MIT
5
//! momentjs.com
6

    
7
;(function (global, factory) {
8
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9
    typeof define === 'function' && define.amd ? define(factory) :
10
    global.moment = factory()
11
}(this, (function () { 'use strict';
12

    
13
var hookCallback;
14

    
15
function hooks () {
16
    return hookCallback.apply(null, arguments);
17
}
18

    
19
// This is done to register the method called with moment()
20
// without creating circular dependencies.
21
function setHookCallback (callback) {
22
    hookCallback = callback;
23
}
24

    
25
function isArray(input) {
26
    return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
27
}
28

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

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

    
49
function isUndefined(input) {
50
    return input === void 0;
51
}
52

    
53
function isNumber(input) {
54
    return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
55
}
56

    
57
function isDate(input) {
58
    return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
59
}
60

    
61
function map(arr, fn) {
62
    var res = [], i;
63
    for (i = 0; i < arr.length; ++i) {
64
        res.push(fn(arr[i], i));
65
    }
66
    return res;
67
}
68

    
69
function hasOwnProp(a, b) {
70
    return Object.prototype.hasOwnProperty.call(a, b);
71
}
72

    
73
function extend(a, b) {
74
    for (var i in b) {
75
        if (hasOwnProp(b, i)) {
76
            a[i] = b[i];
77
        }
78
    }
79

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

    
84
    if (hasOwnProp(b, 'valueOf')) {
85
        a.valueOf = b.valueOf;
86
    }
87

    
88
    return a;
89
}
90

    
91
function createUTC (input, format, locale, strict) {
92
    return createLocalOrUTC(input, format, locale, strict, true).utc();
93
}
94

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

    
115
function getParsingFlags(m) {
116
    if (m._pf == null) {
117
        m._pf = defaultParsingFlags();
118
    }
119
    return m._pf;
120
}
121

    
122
var some;
123
if (Array.prototype.some) {
124
    some = Array.prototype.some;
125
} else {
126
    some = function (fun) {
127
        var t = Object(this);
128
        var len = t.length >>> 0;
129

    
130
        for (var i = 0; i < len; i++) {
131
            if (i in t && fun.call(this, t[i], i, t)) {
132
                return true;
133
            }
134
        }
135

    
136
        return false;
137
    };
138
}
139

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

    
157
        if (m._strict) {
158
            isNowValid = isNowValid &&
159
                flags.charsLeftOver === 0 &&
160
                flags.unusedTokens.length === 0 &&
161
                flags.bigHour === undefined;
162
        }
163

    
164
        if (Object.isFrozen == null || !Object.isFrozen(m)) {
165
            m._isValid = isNowValid;
166
        }
167
        else {
168
            return isNowValid;
169
        }
170
    }
171
    return m._isValid;
172
}
173

    
174
function createInvalid (flags) {
175
    var m = createUTC(NaN);
176
    if (flags != null) {
177
        extend(getParsingFlags(m), flags);
178
    }
179
    else {
180
        getParsingFlags(m).userInvalidated = true;
181
    }
182

    
183
    return m;
184
}
185

    
186
// Plugins that add properties should also add the key here (null value),
187
// so we can properly clone ourselves.
188
var momentProperties = hooks.momentProperties = [];
189

    
190
function copyConfig(to, from) {
191
    var i, prop, val;
192

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

    
224
    if (momentProperties.length > 0) {
225
        for (i = 0; i < momentProperties.length; i++) {
226
            prop = momentProperties[i];
227
            val = from[prop];
228
            if (!isUndefined(val)) {
229
                to[prop] = val;
230
            }
231
        }
232
    }
233

    
234
    return to;
235
}
236

    
237
var updateInProgress = false;
238

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

    
255
function isMoment (obj) {
256
    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
257
}
258

    
259
function absFloor (number) {
260
    if (number < 0) {
261
        // -0 -> 0
262
        return Math.ceil(number) || 0;
263
    } else {
264
        return Math.floor(number);
265
    }
266
}
267

    
268
function toInt(argumentForCoercion) {
269
    var coercedNumber = +argumentForCoercion,
270
        value = 0;
271

    
272
    if (coercedNumber !== 0 && isFinite(coercedNumber)) {
273
        value = absFloor(coercedNumber);
274
    }
275

    
276
    return value;
277
}
278

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

    
294
function warn(msg) {
295
    if (hooks.suppressDeprecationWarnings === false &&
296
            (typeof console !==  'undefined') && console.warn) {
297
        console.warn('Deprecation warning: ' + msg);
298
    }
299
}
300

    
301
function deprecate(msg, fn) {
302
    var firstTime = true;
303

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

    
331
var deprecations = {};
332

    
333
function deprecateSimple(name, msg) {
334
    if (hooks.deprecationHandler != null) {
335
        hooks.deprecationHandler(name, msg);
336
    }
337
    if (!deprecations[name]) {
338
        warn(msg);
339
        deprecations[name] = true;
340
    }
341
}
342

    
343
hooks.suppressDeprecationWarnings = false;
344
hooks.deprecationHandler = null;
345

    
346
function isFunction(input) {
347
    return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
348
}
349

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

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

    
395
function Locale(config) {
396
    if (config != null) {
397
        this.set(config);
398
    }
399
}
400

    
401
var keys;
402

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

    
417
var defaultCalendar = {
418
    sameDay : '[Today at] LT',
419
    nextDay : '[Tomorrow at] LT',
420
    nextWeek : 'dddd [at] LT',
421
    lastDay : '[Yesterday at] LT',
422
    lastWeek : '[Last] dddd [at] LT',
423
    sameElse : 'L'
424
};
425

    
426
function calendar (key, mom, now) {
427
    var output = this._calendar[key] || this._calendar['sameElse'];
428
    return isFunction(output) ? output.call(mom, now) : output;
429
}
430

    
431
var defaultLongDateFormat = {
432
    LTS  : 'h:mm:ss A',
433
    LT   : 'h:mm A',
434
    L    : 'MM/DD/YYYY',
435
    LL   : 'MMMM D, YYYY',
436
    LLL  : 'MMMM D, YYYY h:mm A',
437
    LLLL : 'dddd, MMMM D, YYYY h:mm A'
438
};
439

    
440
function longDateFormat (key) {
441
    var format = this._longDateFormat[key],
442
        formatUpper = this._longDateFormat[key.toUpperCase()];
443

    
444
    if (format || !formatUpper) {
445
        return format;
446
    }
447

    
448
    this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
449
        return val.slice(1);
450
    });
451

    
452
    return this._longDateFormat[key];
453
}
454

    
455
var defaultInvalidDate = 'Invalid date';
456

    
457
function invalidDate () {
458
    return this._invalidDate;
459
}
460

    
461
var defaultOrdinal = '%d';
462
var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
463

    
464
function ordinal (number) {
465
    return this._ordinal.replace('%d', number);
466
}
467

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

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

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

    
497
var aliases = {};
498

    
499
function addUnitAlias (unit, shorthand) {
500
    var lowerCase = unit.toLowerCase();
501
    aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
502
}
503

    
504
function normalizeUnits(units) {
505
    return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
506
}
507

    
508
function normalizeObjectUnits(inputObject) {
509
    var normalizedInput = {},
510
        normalizedProp,
511
        prop;
512

    
513
    for (prop in inputObject) {
514
        if (hasOwnProp(inputObject, prop)) {
515
            normalizedProp = normalizeUnits(prop);
516
            if (normalizedProp) {
517
                normalizedInput[normalizedProp] = inputObject[prop];
518
            }
519
        }
520
    }
521

    
522
    return normalizedInput;
523
}
524

    
525
var priorities = {};
526

    
527
function addUnitPriority(unit, priority) {
528
    priorities[unit] = priority;
529
}
530

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

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

    
550
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;
551

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

    
554
var formatFunctions = {};
555

    
556
var formatTokenFunctions = {};
557

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

    
584
function removeFormattingTokens(input) {
585
    if (input.match(/\[[\s\S]/)) {
586
        return input.replace(/^\[|\]$/g, '');
587
    }
588
    return input.replace(/\\/g, '');
589
}
590

    
591
function makeFormatFunction(format) {
592
    var array = format.match(formattingTokens), i, length;
593

    
594
    for (i = 0, length = array.length; i < length; i++) {
595
        if (formatTokenFunctions[array[i]]) {
596
            array[i] = formatTokenFunctions[array[i]];
597
        } else {
598
            array[i] = removeFormattingTokens(array[i]);
599
        }
600
    }
601

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

    
611
// format date using native date object
612
function formatMoment(m, format) {
613
    if (!m.isValid()) {
614
        return m.localeData().invalidDate();
615
    }
616

    
617
    format = expandFormat(format, m.localeData());
618
    formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
619

    
620
    return formatFunctions[format](m);
621
}
622

    
623
function expandFormat(format, locale) {
624
    var i = 5;
625

    
626
    function replaceLongDateFormatTokens(input) {
627
        return locale.longDateFormat(input) || input;
628
    }
629

    
630
    localFormattingTokens.lastIndex = 0;
631
    while (i >= 0 && localFormattingTokens.test(format)) {
632
        format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
633
        localFormattingTokens.lastIndex = 0;
634
        i -= 1;
635
    }
636

    
637
    return format;
638
}
639

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

    
652
var matchUnsigned  = /\d+/;           //       0 - inf
653
var matchSigned    = /[+-]?\d+/;      //    -inf - inf
654

    
655
var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
656
var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
657

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

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

    
664

    
665
var regexes = {};
666

    
667
function addRegexToken (token, regex, strictRegex) {
668
    regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
669
        return (isStrict && strictRegex) ? strictRegex : regex;
670
    };
671
}
672

    
673
function getParseRegexForToken (token, config) {
674
    if (!hasOwnProp(regexes, token)) {
675
        return new RegExp(unescapeFormat(token));
676
    }
677

    
678
    return regexes[token](config._strict, config._locale);
679
}
680

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

    
688
function regexEscape(s) {
689
    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
690
}
691

    
692
var tokens = {};
693

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

    
709
function addWeekParseToken (token, callback) {
710
    addParseToken(token, function (input, array, config, token) {
711
        config._w = config._w || {};
712
        callback(input, config._w, config, token);
713
    });
714
}
715

    
716
function addTimeToArrayFromToken(token, input, config) {
717
    if (input != null && hasOwnProp(tokens, token)) {
718
        tokens[token](input, config._a, config, token);
719
    }
720
}
721

    
722
var YEAR = 0;
723
var MONTH = 1;
724
var DATE = 2;
725
var HOUR = 3;
726
var MINUTE = 4;
727
var SECOND = 5;
728
var MILLISECOND = 6;
729
var WEEK = 7;
730
var WEEKDAY = 8;
731

    
732
// FORMATTING
733

    
734
addFormatToken('Y', 0, 0, function () {
735
    var y = this.year();
736
    return y <= 9999 ? '' + y : '+' + y;
737
});
738

    
739
addFormatToken(0, ['YY', 2], 0, function () {
740
    return this.year() % 100;
741
});
742

    
743
addFormatToken(0, ['YYYY',   4],       0, 'year');
744
addFormatToken(0, ['YYYYY',  5],       0, 'year');
745
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
746

    
747
// ALIASES
748

    
749
addUnitAlias('year', 'y');
750

    
751
// PRIORITIES
752

    
753
addUnitPriority('year', 1);
754

    
755
// PARSING
756

    
757
addRegexToken('Y',      matchSigned);
758
addRegexToken('YY',     match1to2, match2);
759
addRegexToken('YYYY',   match1to4, match4);
760
addRegexToken('YYYYY',  match1to6, match6);
761
addRegexToken('YYYYYY', match1to6, match6);
762

    
763
addParseToken(['YYYYY', 'YYYYYY'], YEAR);
764
addParseToken('YYYY', function (input, array) {
765
    array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
766
});
767
addParseToken('YY', function (input, array) {
768
    array[YEAR] = hooks.parseTwoDigitYear(input);
769
});
770
addParseToken('Y', function (input, array) {
771
    array[YEAR] = parseInt(input, 10);
772
});
773

    
774
// HELPERS
775

    
776
function daysInYear(year) {
777
    return isLeapYear(year) ? 366 : 365;
778
}
779

    
780
function isLeapYear(year) {
781
    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
782
}
783

    
784
// HOOKS
785

    
786
hooks.parseTwoDigitYear = function (input) {
787
    return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
788
};
789

    
790
// MOMENTS
791

    
792
var getSetYear = makeGetSet('FullYear', true);
793

    
794
function getIsLeapYear () {
795
    return isLeapYear(this.year());
796
}
797

    
798
function makeGetSet (unit, keepTime) {
799
    return function (value) {
800
        if (value != null) {
801
            set$1(this, unit, value);
802
            hooks.updateOffset(this, keepTime);
803
            return this;
804
        } else {
805
            return get(this, unit);
806
        }
807
    };
808
}
809

    
810
function get (mom, unit) {
811
    return mom.isValid() ?
812
        mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
813
}
814

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

    
826
// MOMENTS
827

    
828
function stringGet (units) {
829
    units = normalizeUnits(units);
830
    if (isFunction(this[units])) {
831
        return this[units]();
832
    }
833
    return this;
834
}
835

    
836

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

    
853
function mod(n, x) {
854
    return ((n % x) + x) % x;
855
}
856

    
857
var indexOf;
858

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

    
874
function daysInMonth(year, month) {
875
    if (isNaN(year) || isNaN(month)) {
876
        return NaN;
877
    }
878
    var modMonth = mod(month, 12);
879
    year += (month - modMonth) / 12;
880
    return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
881
}
882

    
883
// FORMATTING
884

    
885
addFormatToken('M', ['MM', 2], 'Mo', function () {
886
    return this.month() + 1;
887
});
888

    
889
addFormatToken('MMM', 0, 0, function (format) {
890
    return this.localeData().monthsShort(this, format);
891
});
892

    
893
addFormatToken('MMMM', 0, 0, function (format) {
894
    return this.localeData().months(this, format);
895
});
896

    
897
// ALIASES
898

    
899
addUnitAlias('month', 'M');
900

    
901
// PRIORITY
902

    
903
addUnitPriority('month', 8);
904

    
905
// PARSING
906

    
907
addRegexToken('M',    match1to2);
908
addRegexToken('MM',   match1to2, match2);
909
addRegexToken('MMM',  function (isStrict, locale) {
910
    return locale.monthsShortRegex(isStrict);
911
});
912
addRegexToken('MMMM', function (isStrict, locale) {
913
    return locale.monthsRegex(isStrict);
914
});
915

    
916
addParseToken(['M', 'MM'], function (input, array) {
917
    array[MONTH] = toInt(input) - 1;
918
});
919

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

    
930
// LOCALES
931

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

    
943
var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
944
function localeMonthsShort (m, format) {
945
    if (!m) {
946
        return isArray(this._monthsShort) ? this._monthsShort :
947
            this._monthsShort['standalone'];
948
    }
949
    return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
950
        this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
951
}
952

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

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

    
994
function localeMonthsParse (monthName, format, strict) {
995
    var i, mom, regex;
996

    
997
    if (this._monthsParseExact) {
998
        return handleStrictParse.call(this, monthName, format, strict);
999
    }
1000

    
1001
    if (!this._monthsParse) {
1002
        this._monthsParse = [];
1003
        this._longMonthsParse = [];
1004
        this._shortMonthsParse = [];
1005
    }
1006

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

    
1032
// MOMENTS
1033

    
1034
function setMonth (mom, value) {
1035
    var dayOfMonth;
1036

    
1037
    if (!mom.isValid()) {
1038
        // No op
1039
        return mom;
1040
    }
1041

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

    
1054
    dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
1055
    mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
1056
    return mom;
1057
}
1058

    
1059
function getSetMonth (value) {
1060
    if (value != null) {
1061
        setMonth(this, value);
1062
        hooks.updateOffset(this, true);
1063
        return this;
1064
    } else {
1065
        return get(this, 'Month');
1066
    }
1067
}
1068

    
1069
function getDaysInMonth () {
1070
    return daysInMonth(this.year(), this.month());
1071
}
1072

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

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

    
1113
function computeMonthsParse () {
1114
    function cmpLenRev(a, b) {
1115
        return b.length - a.length;
1116
    }
1117

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

    
1141
    this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1142
    this._monthsShortRegex = this._monthsRegex;
1143
    this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1144
    this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
1145
}
1146

    
1147
function createDate (y, m, d, h, M, s, ms) {
1148
    // can't just apply() to create a date:
1149
    // https://stackoverflow.com/q/181348
1150
    var date = new Date(y, m, d, h, M, s, ms);
1151

    
1152
    // the date constructor remaps years 0-99 to 1900-1999
1153
    if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
1154
        date.setFullYear(y);
1155
    }
1156
    return date;
1157
}
1158

    
1159
function createUTCDate (y) {
1160
    var date = new Date(Date.UTC.apply(null, arguments));
1161

    
1162
    // the Date.UTC function remaps years 0-99 to 1900-1999
1163
    if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
1164
        date.setUTCFullYear(y);
1165
    }
1166
    return date;
1167
}
1168

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

    
1176
    return -fwdlw + fwd - 1;
1177
}
1178

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

    
1186
    if (dayOfYear <= 0) {
1187
        resYear = year - 1;
1188
        resDayOfYear = daysInYear(resYear) + dayOfYear;
1189
    } else if (dayOfYear > daysInYear(year)) {
1190
        resYear = year + 1;
1191
        resDayOfYear = dayOfYear - daysInYear(year);
1192
    } else {
1193
        resYear = year;
1194
        resDayOfYear = dayOfYear;
1195
    }
1196

    
1197
    return {
1198
        year: resYear,
1199
        dayOfYear: resDayOfYear
1200
    };
1201
}
1202

    
1203
function weekOfYear(mom, dow, doy) {
1204
    var weekOffset = firstWeekOffset(mom.year(), dow, doy),
1205
        week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
1206
        resWeek, resYear;
1207

    
1208
    if (week < 1) {
1209
        resYear = mom.year() - 1;
1210
        resWeek = week + weeksInYear(resYear, dow, doy);
1211
    } else if (week > weeksInYear(mom.year(), dow, doy)) {
1212
        resWeek = week - weeksInYear(mom.year(), dow, doy);
1213
        resYear = mom.year() + 1;
1214
    } else {
1215
        resYear = mom.year();
1216
        resWeek = week;
1217
    }
1218

    
1219
    return {
1220
        week: resWeek,
1221
        year: resYear
1222
    };
1223
}
1224

    
1225
function weeksInYear(year, dow, doy) {
1226
    var weekOffset = firstWeekOffset(year, dow, doy),
1227
        weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
1228
    return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
1229
}
1230

    
1231
// FORMATTING
1232

    
1233
addFormatToken('w', ['ww', 2], 'wo', 'week');
1234
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
1235

    
1236
// ALIASES
1237

    
1238
addUnitAlias('week', 'w');
1239
addUnitAlias('isoWeek', 'W');
1240

    
1241
// PRIORITIES
1242

    
1243
addUnitPriority('week', 5);
1244
addUnitPriority('isoWeek', 5);
1245

    
1246
// PARSING
1247

    
1248
addRegexToken('w',  match1to2);
1249
addRegexToken('ww', match1to2, match2);
1250
addRegexToken('W',  match1to2);
1251
addRegexToken('WW', match1to2, match2);
1252

    
1253
addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
1254
    week[token.substr(0, 1)] = toInt(input);
1255
});
1256

    
1257
// HELPERS
1258

    
1259
// LOCALES
1260

    
1261
function localeWeek (mom) {
1262
    return weekOfYear(mom, this._week.dow, this._week.doy).week;
1263
}
1264

    
1265
var defaultLocaleWeek = {
1266
    dow : 0, // Sunday is the first day of the week.
1267
    doy : 6  // The week that contains Jan 1st is the first week of the year.
1268
};
1269

    
1270
function localeFirstDayOfWeek () {
1271
    return this._week.dow;
1272
}
1273

    
1274
function localeFirstDayOfYear () {
1275
    return this._week.doy;
1276
}
1277

    
1278
// MOMENTS
1279

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

    
1285
function getSetISOWeek (input) {
1286
    var week = weekOfYear(this, 1, 4).week;
1287
    return input == null ? week : this.add((input - week) * 7, 'd');
1288
}
1289

    
1290
// FORMATTING
1291

    
1292
addFormatToken('d', 0, 'do', 'day');
1293

    
1294
addFormatToken('dd', 0, 0, function (format) {
1295
    return this.localeData().weekdaysMin(this, format);
1296
});
1297

    
1298
addFormatToken('ddd', 0, 0, function (format) {
1299
    return this.localeData().weekdaysShort(this, format);
1300
});
1301

    
1302
addFormatToken('dddd', 0, 0, function (format) {
1303
    return this.localeData().weekdays(this, format);
1304
});
1305

    
1306
addFormatToken('e', 0, 0, 'weekday');
1307
addFormatToken('E', 0, 0, 'isoWeekday');
1308

    
1309
// ALIASES
1310

    
1311
addUnitAlias('day', 'd');
1312
addUnitAlias('weekday', 'e');
1313
addUnitAlias('isoWeekday', 'E');
1314

    
1315
// PRIORITY
1316
addUnitPriority('day', 11);
1317
addUnitPriority('weekday', 11);
1318
addUnitPriority('isoWeekday', 11);
1319

    
1320
// PARSING
1321

    
1322
addRegexToken('d',    match1to2);
1323
addRegexToken('e',    match1to2);
1324
addRegexToken('E',    match1to2);
1325
addRegexToken('dd',   function (isStrict, locale) {
1326
    return locale.weekdaysMinRegex(isStrict);
1327
});
1328
addRegexToken('ddd',   function (isStrict, locale) {
1329
    return locale.weekdaysShortRegex(isStrict);
1330
});
1331
addRegexToken('dddd',   function (isStrict, locale) {
1332
    return locale.weekdaysRegex(isStrict);
1333
});
1334

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

    
1345
addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
1346
    week[token] = toInt(input);
1347
});
1348

    
1349
// HELPERS
1350

    
1351
function parseWeekday(input, locale) {
1352
    if (typeof input !== 'string') {
1353
        return input;
1354
    }
1355

    
1356
    if (!isNaN(input)) {
1357
        return parseInt(input, 10);
1358
    }
1359

    
1360
    input = locale.weekdaysParse(input);
1361
    if (typeof input === 'number') {
1362
        return input;
1363
    }
1364

    
1365
    return null;
1366
}
1367

    
1368
function parseIsoWeekday(input, locale) {
1369
    if (typeof input === 'string') {
1370
        return locale.weekdaysParse(input) % 7 || 7;
1371
    }
1372
    return isNaN(input) ? null : input;
1373
}
1374

    
1375
// LOCALES
1376

    
1377
var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
1378
function localeWeekdays (m, format) {
1379
    if (!m) {
1380
        return isArray(this._weekdays) ? this._weekdays :
1381
            this._weekdays['standalone'];
1382
    }
1383
    return isArray(this._weekdays) ? this._weekdays[m.day()] :
1384
        this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
1385
}
1386

    
1387
var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
1388
function localeWeekdaysShort (m) {
1389
    return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
1390
}
1391

    
1392
var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
1393
function localeWeekdaysMin (m) {
1394
    return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
1395
}
1396

    
1397
function handleStrictParse$1(weekdayName, format, strict) {
1398
    var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
1399
    if (!this._weekdaysParse) {
1400
        this._weekdaysParse = [];
1401
        this._shortWeekdaysParse = [];
1402
        this._minWeekdaysParse = [];
1403

    
1404
        for (i = 0; i < 7; ++i) {
1405
            mom = createUTC([2000, 1]).day(i);
1406
            this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
1407
            this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
1408
            this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
1409
        }
1410
    }
1411

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

    
1461
function localeWeekdaysParse (weekdayName, format, strict) {
1462
    var i, mom, regex;
1463

    
1464
    if (this._weekdaysParseExact) {
1465
        return handleStrictParse$1.call(this, weekdayName, format, strict);
1466
    }
1467

    
1468
    if (!this._weekdaysParse) {
1469
        this._weekdaysParse = [];
1470
        this._minWeekdaysParse = [];
1471
        this._shortWeekdaysParse = [];
1472
        this._fullWeekdaysParse = [];
1473
    }
1474

    
1475
    for (i = 0; i < 7; i++) {
1476
        // make the regex if we don't have it already
1477

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

    
1501
// MOMENTS
1502

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

    
1516
function getSetLocaleDayOfWeek (input) {
1517
    if (!this.isValid()) {
1518
        return input != null ? this : NaN;
1519
    }
1520
    var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
1521
    return input == null ? weekday : this.add(input - weekday, 'd');
1522
}
1523

    
1524
function getSetISODayOfWeek (input) {
1525
    if (!this.isValid()) {
1526
        return input != null ? this : NaN;
1527
    }
1528

    
1529
    // behaves the same as moment#day except
1530
    // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
1531
    // as a setter, sunday should belong to the previous week.
1532

    
1533
    if (input != null) {
1534
        var weekday = parseIsoWeekday(input, this.localeData());
1535
        return this.day(this.day() % 7 ? weekday : weekday - 7);
1536
    } else {
1537
        return this.day() || 7;
1538
    }
1539
}
1540

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

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

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

    
1601

    
1602
function computeWeekdaysParse () {
1603
    function cmpLenRev(a, b) {
1604
        return b.length - a.length;
1605
    }
1606

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

    
1634
    this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
1635
    this._weekdaysShortRegex = this._weekdaysRegex;
1636
    this._weekdaysMinRegex = this._weekdaysRegex;
1637

    
1638
    this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
1639
    this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
1640
    this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
1641
}
1642

    
1643
// FORMATTING
1644

    
1645
function hFormat() {
1646
    return this.hours() % 12 || 12;
1647
}
1648

    
1649
function kFormat() {
1650
    return this.hours() || 24;
1651
}
1652

    
1653
addFormatToken('H', ['HH', 2], 0, 'hour');
1654
addFormatToken('h', ['hh', 2], 0, hFormat);
1655
addFormatToken('k', ['kk', 2], 0, kFormat);
1656

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

    
1661
addFormatToken('hmmss', 0, 0, function () {
1662
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
1663
        zeroFill(this.seconds(), 2);
1664
});
1665

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

    
1670
addFormatToken('Hmmss', 0, 0, function () {
1671
    return '' + this.hours() + zeroFill(this.minutes(), 2) +
1672
        zeroFill(this.seconds(), 2);
1673
});
1674

    
1675
function meridiem (token, lowercase) {
1676
    addFormatToken(token, 0, 0, function () {
1677
        return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
1678
    });
1679
}
1680

    
1681
meridiem('a', true);
1682
meridiem('A', false);
1683

    
1684
// ALIASES
1685

    
1686
addUnitAlias('hour', 'h');
1687

    
1688
// PRIORITY
1689
addUnitPriority('hour', 13);
1690

    
1691
// PARSING
1692

    
1693
function matchMeridiem (isStrict, locale) {
1694
    return locale._meridiemParse;
1695
}
1696

    
1697
addRegexToken('a',  matchMeridiem);
1698
addRegexToken('A',  matchMeridiem);
1699
addRegexToken('H',  match1to2);
1700
addRegexToken('h',  match1to2);
1701
addRegexToken('k',  match1to2);
1702
addRegexToken('HH', match1to2, match2);
1703
addRegexToken('hh', match1to2, match2);
1704
addRegexToken('kk', match1to2, match2);
1705

    
1706
addRegexToken('hmm', match3to4);
1707
addRegexToken('hmmss', match5to6);
1708
addRegexToken('Hmm', match3to4);
1709
addRegexToken('Hmmss', match5to6);
1710

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

    
1751
// LOCALES
1752

    
1753
function localeIsPM (input) {
1754
    // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
1755
    // Using charAt should be more compatible.
1756
    return ((input + '').toLowerCase().charAt(0) === 'p');
1757
}
1758

    
1759
var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
1760
function localeMeridiem (hours, minutes, isLower) {
1761
    if (hours > 11) {
1762
        return isLower ? 'pm' : 'PM';
1763
    } else {
1764
        return isLower ? 'am' : 'AM';
1765
    }
1766
}
1767

    
1768

    
1769
// MOMENTS
1770

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

    
1777
// months
1778
// week
1779
// weekdays
1780
// meridiem
1781
var baseConfig = {
1782
    calendar: defaultCalendar,
1783
    longDateFormat: defaultLongDateFormat,
1784
    invalidDate: defaultInvalidDate,
1785
    ordinal: defaultOrdinal,
1786
    dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
1787
    relativeTime: defaultRelativeTime,
1788

    
1789
    months: defaultLocaleMonths,
1790
    monthsShort: defaultLocaleMonthsShort,
1791

    
1792
    week: defaultLocaleWeek,
1793

    
1794
    weekdays: defaultLocaleWeekdays,
1795
    weekdaysMin: defaultLocaleWeekdaysMin,
1796
    weekdaysShort: defaultLocaleWeekdaysShort,
1797

    
1798
    meridiemParse: defaultLocaleMeridiemParse
1799
};
1800

    
1801
// internal storage for locale config files
1802
var locales = {};
1803
var localeFamilies = {};
1804
var globalLocale;
1805

    
1806
function normalizeLocale(key) {
1807
    return key ? key.toLowerCase().replace('_', '-') : key;
1808
}
1809

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

    
1816
    while (i < names.length) {
1817
        split = normalizeLocale(names[i]).split('-');
1818
        j = split.length;
1819
        next = normalizeLocale(names[i + 1]);
1820
        next = next ? next.split('-') : null;
1821
        while (j > 0) {
1822
            locale = loadLocale(split.slice(0, j).join('-'));
1823
            if (locale) {
1824
                return locale;
1825
            }
1826
            if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
1827
                //the next array item is better than a shallower substring of this one
1828
                break;
1829
            }
1830
            j--;
1831
        }
1832
        i++;
1833
    }
1834
    return null;
1835
}
1836

    
1837
function loadLocale(name) {
1838
    var oldLocale = null;
1839
    // TODO: Find a better way to register and load all the locales in Node
1840
    if (!locales[name] && (typeof module !== 'undefined') &&
1841
            module && module.exports) {
1842
        try {
1843
            oldLocale = globalLocale._abbr;
1844
            var aliasedRequire = require;
1845
            aliasedRequire('./locale/' + name);
1846
            getSetGlobalLocale(oldLocale);
1847
        } catch (e) {}
1848
    }
1849
    return locales[name];
1850
}
1851

    
1852
// This function will load locale and then set the global locale.  If
1853
// no arguments are passed in, it will simply return the current global
1854
// locale key.
1855
function getSetGlobalLocale (key, values) {
1856
    var data;
1857
    if (key) {
1858
        if (isUndefined(values)) {
1859
            data = getLocale(key);
1860
        }
1861
        else {
1862
            data = defineLocale(key, values);
1863
        }
1864

    
1865
        if (data) {
1866
            // moment.duration._locale = moment._locale = data;
1867
            globalLocale = data;
1868
        }
1869
    }
1870

    
1871
    return globalLocale._abbr;
1872
}
1873

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

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

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

    
1912

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

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

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

    
1949
// returns locale data
1950
function getLocale (key) {
1951
    var locale;
1952

    
1953
    if (key && key._locale && key._locale._abbr) {
1954
        key = key._locale._abbr;
1955
    }
1956

    
1957
    if (!key) {
1958
        return globalLocale;
1959
    }
1960

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

    
1970
    return chooseLocale(key);
1971
}
1972

    
1973
function listLocales() {
1974
    return keys(locales);
1975
}
1976

    
1977
function checkOverflow (m) {
1978
    var overflow;
1979
    var a = m._a;
1980

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

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

    
2001
        getParsingFlags(m).overflow = overflow;
2002
    }
2003

    
2004
    return m;
2005
}
2006

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

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

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

    
2034
    if (config._d) {
2035
        return;
2036
    }
2037

    
2038
    currentDate = currentDateArray(config);
2039

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2122
        var curWeek = weekOfYear(createLocal(), dow, doy);
2123

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

    
2126
        // Default to current week.
2127
        week = defaults(w.w, curWeek.week);
2128

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

    
2157
// iso 8601 regex
2158
// 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)
2159
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)?)?$/;
2160
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)?)?$/;
2161

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

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

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

    
2192
var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
2193

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

    
2201
    if (match) {
2202
        getParsingFlags(config).iso = true;
2203

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

    
2247
// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
2248
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}))$/;
2249

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

    
2259
    if (secondStr) {
2260
        result.push(parseInt(secondStr, 10));
2261
    }
2262

    
2263
    return result;
2264
}
2265

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2453
    configFromArray(config);
2454
    checkOverflow(config);
2455
}
2456

    
2457

    
2458
function meridiemFixWrap (locale, hour, meridiem) {
2459
    var isPm;
2460

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

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

    
2488
        scoreToBeat,
2489
        i,
2490
        currentScore;
2491

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

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

    
2507
        if (!isValid(tempConfig)) {
2508
            continue;
2509
        }
2510

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

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

    
2517
        getParsingFlags(tempConfig).score = currentScore;
2518

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

    
2525
    extend(config, bestMoment || tempConfig);
2526
}
2527

    
2528
function configFromObject(config) {
2529
    if (config._d) {
2530
        return;
2531
    }
2532

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

    
2538
    configFromArray(config);
2539
}
2540

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

    
2549
    return res;
2550
}
2551

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

    
2556
    config._locale = config._locale || getLocale(config._l);
2557

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

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

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

    
2578
    if (!isValid(config)) {
2579
        config._d = null;
2580
    }
2581

    
2582
    return config;
2583
}
2584

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

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

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

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

    
2629
    return createFromConfig(c);
2630
}
2631

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

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

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

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

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

    
2686
    return pickBy('isBefore', args);
2687
}
2688

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

    
2692
    return pickBy('isAfter', args);
2693
}
2694

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

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

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

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

    
2720
    return true;
2721
}
2722

    
2723
function isValid$1() {
2724
    return this._isValid;
2725
}
2726

    
2727
function createInvalid$1() {
2728
    return createDuration(NaN);
2729
}
2730

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

    
2743
    this._isValid = isDurationValid(normalizedInput);
2744

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

    
2761
    this._data = {};
2762

    
2763
    this._locale = getLocale();
2764

    
2765
    this._bubble();
2766
}
2767

    
2768
function isDuration (obj) {
2769
    return obj instanceof Duration;
2770
}
2771

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

    
2780
// FORMATTING
2781

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

    
2794
offset('Z', ':');
2795
offset('ZZ', '');
2796

    
2797
// PARSING
2798

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

    
2806
// HELPERS
2807

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

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

    
2816
    if (matches === null) {
2817
        return null;
2818
    }
2819

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

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

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

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

    
2850
// HOOKS
2851

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

    
2856
// MOMENTS
2857

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

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

    
2912
        this.utcOffset(input, keepLocalTime);
2913

    
2914
        return this;
2915
    } else {
2916
        return -this.utcOffset();
2917
    }
2918
}
2919

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

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

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

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

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

    
2957
    return (this.utcOffset() - input) % 60 === 0;
2958
}
2959

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

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

    
2972
    var c = {};
2973

    
2974
    copyConfig(c, this);
2975
    c = prepareConfig(c);
2976

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

    
2985
    return this._isDSTShifted;
2986
}
2987

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

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

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

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

    
3003
// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
3004
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
3005
// and further modified to allow for strings containing both week and day
3006
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)?)?$/;
3007

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

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

    
3055
        duration = {};
3056
        duration.ms = diffRes.milliseconds;
3057
        duration.M = diffRes.months;
3058
    }
3059

    
3060
    ret = new Duration(duration);
3061

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

    
3066
    return ret;
3067
}
3068

    
3069
createDuration.fn = Duration.prototype;
3070
createDuration.invalid = createInvalid$1;
3071

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

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

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

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

    
3092
    return res;
3093
}
3094

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

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

    
3110
    return res;
3111
}
3112

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

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

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

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

    
3141
    updateOffset = updateOffset == null ? true : updateOffset;
3142

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

    
3157
var add      = createAdder(1, 'add');
3158
var subtract = createAdder(-1, 'subtract');
3159

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

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

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

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

    
3182
function clone () {
3183
    return new Moment(this);
3184
}
3185

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

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

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

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

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

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

    
3241
function diff (input, units, asFloat) {
3242
    var that,
3243
        zoneDelta,
3244
        delta, output;
3245

    
3246
    if (!this.isValid()) {
3247
        return NaN;
3248
    }
3249

    
3250
    that = cloneWithOffset(input, this);
3251

    
3252
    if (!that.isValid()) {
3253
        return NaN;
3254
    }
3255

    
3256
    zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
3257

    
3258
    units = normalizeUnits(units);
3259

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

    
3272
    return asFloat ? output : absFloor(output);
3273
}
3274

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

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

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

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

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

    
3303
function toISOString() {
3304
    if (!this.isValid()) {
3305
        return null;
3306
    }
3307
    var m = this.clone().utc();
3308
    if (m.year() < 0 || m.year() > 9999) {
3309
        return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
3310
    }
3311
    if (isFunction(Date.prototype.toISOString)) {
3312
        // native implementation is ~50x faster, use it when we can
3313
        return this.toDate().toISOString();
3314
    }
3315
    return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
3316
}
3317

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

    
3339
    return this.format(prefix + year + datetime + suffix);
3340
}
3341

    
3342
function format (inputString) {
3343
    if (!inputString) {
3344
        inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
3345
    }
3346
    var output = formatMoment(this, inputString);
3347
    return this.localeData().postformat(output);
3348
}
3349

    
3350
function from (time, withoutSuffix) {
3351
    if (this.isValid() &&
3352
            ((isMoment(time) && time.isValid()) ||
3353
             createLocal(time).isValid())) {
3354
        return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
3355
    } else {
3356
        return this.localeData().invalidDate();
3357
    }
3358
}
3359

    
3360
function fromNow (withoutSuffix) {
3361
    return this.from(createLocal(), withoutSuffix);
3362
}
3363

    
3364
function to (time, withoutSuffix) {
3365
    if (this.isValid() &&
3366
            ((isMoment(time) && time.isValid()) ||
3367
             createLocal(time).isValid())) {
3368
        return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
3369
    } else {
3370
        return this.localeData().invalidDate();
3371
    }
3372
}
3373

    
3374
function toNow (withoutSuffix) {
3375
    return this.to(createLocal(), withoutSuffix);
3376
}
3377

    
3378
// If passed a locale key, it will set the locale for this
3379
// instance.  Otherwise, it will return the locale configuration
3380
// variables for this instance.
3381
function locale (key) {
3382
    var newLocaleData;
3383

    
3384
    if (key === undefined) {
3385
        return this._locale._abbr;
3386
    } else {
3387
        newLocaleData = getLocale(key);
3388
        if (newLocaleData != null) {
3389
            this._locale = newLocaleData;
3390
        }
3391
        return this;
3392
    }
3393
}
3394

    
3395
var lang = deprecate(
3396
    'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
3397
    function (key) {
3398
        if (key === undefined) {
3399
            return this.localeData();
3400
        } else {
3401
            return this.locale(key);
3402
        }
3403
    }
3404
);
3405

    
3406
function localeData () {
3407
    return this._locale;
3408
}
3409

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

    
3438
    // weeks are a special case
3439
    if (units === 'week') {
3440
        this.weekday(0);
3441
    }
3442
    if (units === 'isoWeek') {
3443
        this.isoWeekday(1);
3444
    }
3445

    
3446
    // quarters are also special
3447
    if (units === 'quarter') {
3448
        this.month(Math.floor(this.month() / 3) * 3);
3449
    }
3450

    
3451
    return this;
3452
}
3453

    
3454
function endOf (units) {
3455
    units = normalizeUnits(units);
3456
    if (units === undefined || units === 'millisecond') {
3457
        return this;
3458
    }
3459

    
3460
    // 'date' is an alias for 'day', so it should be considered as such.
3461
    if (units === 'date') {
3462
        units = 'day';
3463
    }
3464

    
3465
    return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
3466
}
3467

    
3468
function valueOf () {
3469
    return this._d.valueOf() - ((this._offset || 0) * 60000);
3470
}
3471

    
3472
function unix () {
3473
    return Math.floor(this.valueOf() / 1000);
3474
}
3475

    
3476
function toDate () {
3477
    return new Date(this.valueOf());
3478
}
3479

    
3480
function toArray () {
3481
    var m = this;
3482
    return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
3483
}
3484

    
3485
function toObject () {
3486
    var m = this;
3487
    return {
3488
        years: m.year(),
3489
        months: m.month(),
3490
        date: m.date(),
3491
        hours: m.hours(),
3492
        minutes: m.minutes(),
3493
        seconds: m.seconds(),
3494
        milliseconds: m.milliseconds()
3495
    };
3496
}
3497

    
3498
function toJSON () {
3499
    // new Date(NaN).toJSON() === null
3500
    return this.isValid() ? this.toISOString() : null;
3501
}
3502

    
3503
function isValid$2 () {
3504
    return isValid(this);
3505
}
3506

    
3507
function parsingFlags () {
3508
    return extend({}, getParsingFlags(this));
3509
}
3510

    
3511
function invalidAt () {
3512
    return getParsingFlags(this).overflow;
3513
}
3514

    
3515
function creationData() {
3516
    return {
3517
        input: this._i,
3518
        format: this._f,
3519
        locale: this._locale,
3520
        isUTC: this._isUTC,
3521
        strict: this._strict
3522
    };
3523
}
3524

    
3525
// FORMATTING
3526

    
3527
addFormatToken(0, ['gg', 2], 0, function () {
3528
    return this.weekYear() % 100;
3529
});
3530

    
3531
addFormatToken(0, ['GG', 2], 0, function () {
3532
    return this.isoWeekYear() % 100;
3533
});
3534

    
3535
function addWeekYearFormatToken (token, getter) {
3536
    addFormatToken(0, [token, token.length], 0, getter);
3537
}
3538

    
3539
addWeekYearFormatToken('gggg',     'weekYear');
3540
addWeekYearFormatToken('ggggg',    'weekYear');
3541
addWeekYearFormatToken('GGGG',  'isoWeekYear');
3542
addWeekYearFormatToken('GGGGG', 'isoWeekYear');
3543

    
3544
// ALIASES
3545

    
3546
addUnitAlias('weekYear', 'gg');
3547
addUnitAlias('isoWeekYear', 'GG');
3548

    
3549
// PRIORITY
3550

    
3551
addUnitPriority('weekYear', 1);
3552
addUnitPriority('isoWeekYear', 1);
3553

    
3554

    
3555
// PARSING
3556

    
3557
addRegexToken('G',      matchSigned);
3558
addRegexToken('g',      matchSigned);
3559
addRegexToken('GG',     match1to2, match2);
3560
addRegexToken('gg',     match1to2, match2);
3561
addRegexToken('GGGG',   match1to4, match4);
3562
addRegexToken('gggg',   match1to4, match4);
3563
addRegexToken('GGGGG',  match1to6, match6);
3564
addRegexToken('ggggg',  match1to6, match6);
3565

    
3566
addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
3567
    week[token.substr(0, 2)] = toInt(input);
3568
});
3569

    
3570
addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
3571
    week[token] = hooks.parseTwoDigitYear(input);
3572
});
3573

    
3574
// MOMENTS
3575

    
3576
function getSetWeekYear (input) {
3577
    return getSetWeekYearHelper.call(this,
3578
            input,
3579
            this.week(),
3580
            this.weekday(),
3581
            this.localeData()._week.dow,
3582
            this.localeData()._week.doy);
3583
}
3584

    
3585
function getSetISOWeekYear (input) {
3586
    return getSetWeekYearHelper.call(this,
3587
            input, this.isoWeek(), this.isoWeekday(), 1, 4);
3588
}
3589

    
3590
function getISOWeeksInYear () {
3591
    return weeksInYear(this.year(), 1, 4);
3592
}
3593

    
3594
function getWeeksInYear () {
3595
    var weekInfo = this.localeData()._week;
3596
    return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
3597
}
3598

    
3599
function getSetWeekYearHelper(input, week, weekday, dow, doy) {
3600
    var weeksTarget;
3601
    if (input == null) {
3602
        return weekOfYear(this, dow, doy).year;
3603
    } else {
3604
        weeksTarget = weeksInYear(input, dow, doy);
3605
        if (week > weeksTarget) {
3606
            week = weeksTarget;
3607
        }
3608
        return setWeekAll.call(this, input, week, weekday, dow, doy);
3609
    }
3610
}
3611

    
3612
function setWeekAll(weekYear, week, weekday, dow, doy) {
3613
    var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
3614
        date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
3615

    
3616
    this.year(date.getUTCFullYear());
3617
    this.month(date.getUTCMonth());
3618
    this.date(date.getUTCDate());
3619
    return this;
3620
}
3621

    
3622
// FORMATTING
3623

    
3624
addFormatToken('Q', 0, 'Qo', 'quarter');
3625

    
3626
// ALIASES
3627

    
3628
addUnitAlias('quarter', 'Q');
3629

    
3630
// PRIORITY
3631

    
3632
addUnitPriority('quarter', 7);
3633

    
3634
// PARSING
3635

    
3636
addRegexToken('Q', match1);
3637
addParseToken('Q', function (input, array) {
3638
    array[MONTH] = (toInt(input) - 1) * 3;
3639
});
3640

    
3641
// MOMENTS
3642

    
3643
function getSetQuarter (input) {
3644
    return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
3645
}
3646

    
3647
// FORMATTING
3648

    
3649
addFormatToken('D', ['DD', 2], 'Do', 'date');
3650

    
3651
// ALIASES
3652

    
3653
addUnitAlias('date', 'D');
3654

    
3655
// PRIOROITY
3656
addUnitPriority('date', 9);
3657

    
3658
// PARSING
3659

    
3660
addRegexToken('D',  match1to2);
3661
addRegexToken('DD', match1to2, match2);
3662
addRegexToken('Do', function (isStrict, locale) {
3663
    // TODO: Remove "ordinalParse" fallback in next major release.
3664
    return isStrict ?
3665
      (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
3666
      locale._dayOfMonthOrdinalParseLenient;
3667
});
3668

    
3669
addParseToken(['D', 'DD'], DATE);
3670
addParseToken('Do', function (input, array) {
3671
    array[DATE] = toInt(input.match(match1to2)[0]);
3672
});
3673

    
3674
// MOMENTS
3675

    
3676
var getSetDayOfMonth = makeGetSet('Date', true);
3677

    
3678
// FORMATTING
3679

    
3680
addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
3681

    
3682
// ALIASES
3683

    
3684
addUnitAlias('dayOfYear', 'DDD');
3685

    
3686
// PRIORITY
3687
addUnitPriority('dayOfYear', 4);
3688

    
3689
// PARSING
3690

    
3691
addRegexToken('DDD',  match1to3);
3692
addRegexToken('DDDD', match3);
3693
addParseToken(['DDD', 'DDDD'], function (input, array, config) {
3694
    config._dayOfYear = toInt(input);
3695
});
3696

    
3697
// HELPERS
3698

    
3699
// MOMENTS
3700

    
3701
function getSetDayOfYear (input) {
3702
    var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
3703
    return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
3704
}
3705

    
3706
// FORMATTING
3707

    
3708
addFormatToken('m', ['mm', 2], 0, 'minute');
3709

    
3710
// ALIASES
3711

    
3712
addUnitAlias('minute', 'm');
3713

    
3714
// PRIORITY
3715

    
3716
addUnitPriority('minute', 14);
3717

    
3718
// PARSING
3719

    
3720
addRegexToken('m',  match1to2);
3721
addRegexToken('mm', match1to2, match2);
3722
addParseToken(['m', 'mm'], MINUTE);
3723

    
3724
// MOMENTS
3725

    
3726
var getSetMinute = makeGetSet('Minutes', false);
3727

    
3728
// FORMATTING
3729

    
3730
addFormatToken('s', ['ss', 2], 0, 'second');
3731

    
3732
// ALIASES
3733

    
3734
addUnitAlias('second', 's');
3735

    
3736
// PRIORITY
3737

    
3738
addUnitPriority('second', 15);
3739

    
3740
// PARSING
3741

    
3742
addRegexToken('s',  match1to2);
3743
addRegexToken('ss', match1to2, match2);
3744
addParseToken(['s', 'ss'], SECOND);
3745

    
3746
// MOMENTS
3747

    
3748
var getSetSecond = makeGetSet('Seconds', false);
3749

    
3750
// FORMATTING
3751

    
3752
addFormatToken('S', 0, 0, function () {
3753
    return ~~(this.millisecond() / 100);
3754
});
3755

    
3756
addFormatToken(0, ['SS', 2], 0, function () {
3757
    return ~~(this.millisecond() / 10);
3758
});
3759

    
3760
addFormatToken(0, ['SSS', 3], 0, 'millisecond');
3761
addFormatToken(0, ['SSSS', 4], 0, function () {
3762
    return this.millisecond() * 10;
3763
});
3764
addFormatToken(0, ['SSSSS', 5], 0, function () {
3765
    return this.millisecond() * 100;
3766
});
3767
addFormatToken(0, ['SSSSSS', 6], 0, function () {
3768
    return this.millisecond() * 1000;
3769
});
3770
addFormatToken(0, ['SSSSSSS', 7], 0, function () {
3771
    return this.millisecond() * 10000;
3772
});
3773
addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
3774
    return this.millisecond() * 100000;
3775
});
3776
addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
3777
    return this.millisecond() * 1000000;
3778
});
3779

    
3780

    
3781
// ALIASES
3782

    
3783
addUnitAlias('millisecond', 'ms');
3784

    
3785
// PRIORITY
3786

    
3787
addUnitPriority('millisecond', 16);
3788

    
3789
// PARSING
3790

    
3791
addRegexToken('S',    match1to3, match1);
3792
addRegexToken('SS',   match1to3, match2);
3793
addRegexToken('SSS',  match1to3, match3);
3794

    
3795
var token;
3796
for (token = 'SSSS'; token.length <= 9; token += 'S') {
3797
    addRegexToken(token, matchUnsigned);
3798
}
3799

    
3800
function parseMs(input, array) {
3801
    array[MILLISECOND] = toInt(('0.' + input) * 1000);
3802
}
3803

    
3804
for (token = 'S'; token.length <= 9; token += 'S') {
3805
    addParseToken(token, parseMs);
3806
}
3807
// MOMENTS
3808

    
3809
var getSetMillisecond = makeGetSet('Milliseconds', false);
3810

    
3811
// FORMATTING
3812

    
3813
addFormatToken('z',  0, 0, 'zoneAbbr');
3814
addFormatToken('zz', 0, 0, 'zoneName');
3815

    
3816
// MOMENTS
3817

    
3818
function getZoneAbbr () {
3819
    return this._isUTC ? 'UTC' : '';
3820
}
3821

    
3822
function getZoneName () {
3823
    return this._isUTC ? 'Coordinated Universal Time' : '';
3824
}
3825

    
3826
var proto = Moment.prototype;
3827

    
3828
proto.add               = add;
3829
proto.calendar          = calendar$1;
3830
proto.clone             = clone;
3831
proto.diff              = diff;
3832
proto.endOf             = endOf;
3833
proto.format            = format;
3834
proto.from              = from;
3835
proto.fromNow           = fromNow;
3836
proto.to                = to;
3837
proto.toNow             = toNow;
3838
proto.get               = stringGet;
3839
proto.invalidAt         = invalidAt;
3840
proto.isAfter           = isAfter;
3841
proto.isBefore          = isBefore;
3842
proto.isBetween         = isBetween;
3843
proto.isSame            = isSame;
3844
proto.isSameOrAfter     = isSameOrAfter;
3845
proto.isSameOrBefore    = isSameOrBefore;
3846
proto.isValid           = isValid$2;
3847
proto.lang              = lang;
3848
proto.locale            = locale;
3849
proto.localeData        = localeData;
3850
proto.max               = prototypeMax;
3851
proto.min               = prototypeMin;
3852
proto.parsingFlags      = parsingFlags;
3853
proto.set               = stringSet;
3854
proto.startOf           = startOf;
3855
proto.subtract          = subtract;
3856
proto.toArray           = toArray;
3857
proto.toObject          = toObject;
3858
proto.toDate            = toDate;
3859
proto.toISOString       = toISOString;
3860
proto.inspect           = inspect;
3861
proto.toJSON            = toJSON;
3862
proto.toString          = toString;
3863
proto.unix              = unix;
3864
proto.valueOf           = valueOf;
3865
proto.creationData      = creationData;
3866

    
3867
// Year
3868
proto.year       = getSetYear;
3869
proto.isLeapYear = getIsLeapYear;
3870

    
3871
// Week Year
3872
proto.weekYear    = getSetWeekYear;
3873
proto.isoWeekYear = getSetISOWeekYear;
3874

    
3875
// Quarter
3876
proto.quarter = proto.quarters = getSetQuarter;
3877

    
3878
// Month
3879
proto.month       = getSetMonth;
3880
proto.daysInMonth = getDaysInMonth;
3881

    
3882
// Week
3883
proto.week           = proto.weeks        = getSetWeek;
3884
proto.isoWeek        = proto.isoWeeks     = getSetISOWeek;
3885
proto.weeksInYear    = getWeeksInYear;
3886
proto.isoWeeksInYear = getISOWeeksInYear;
3887

    
3888
// Day
3889
proto.date       = getSetDayOfMonth;
3890
proto.day        = proto.days             = getSetDayOfWeek;
3891
proto.weekday    = getSetLocaleDayOfWeek;
3892
proto.isoWeekday = getSetISODayOfWeek;
3893
proto.dayOfYear  = getSetDayOfYear;
3894

    
3895
// Hour
3896
proto.hour = proto.hours = getSetHour;
3897

    
3898
// Minute
3899
proto.minute = proto.minutes = getSetMinute;
3900

    
3901
// Second
3902
proto.second = proto.seconds = getSetSecond;
3903

    
3904
// Millisecond
3905
proto.millisecond = proto.milliseconds = getSetMillisecond;
3906

    
3907
// Offset
3908
proto.utcOffset            = getSetOffset;
3909
proto.utc                  = setOffsetToUTC;
3910
proto.local                = setOffsetToLocal;
3911
proto.parseZone            = setOffsetToParsedOffset;
3912
proto.hasAlignedHourOffset = hasAlignedHourOffset;
3913
proto.isDST                = isDaylightSavingTime;
3914
proto.isLocal              = isLocal;
3915
proto.isUtcOffset          = isUtcOffset;
3916
proto.isUtc                = isUtc;
3917
proto.isUTC                = isUtc;
3918

    
3919
// Timezone
3920
proto.zoneAbbr = getZoneAbbr;
3921
proto.zoneName = getZoneName;
3922

    
3923
// Deprecations
3924
proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
3925
proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
3926
proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
3927
proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
3928
proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
3929

    
3930
function createUnix (input) {
3931
    return createLocal(input * 1000);
3932
}
3933

    
3934
function createInZone () {
3935
    return createLocal.apply(null, arguments).parseZone();
3936
}
3937

    
3938
function preParsePostFormat (string) {
3939
    return string;
3940
}
3941

    
3942
var proto$1 = Locale.prototype;
3943

    
3944
proto$1.calendar        = calendar;
3945
proto$1.longDateFormat  = longDateFormat;
3946
proto$1.invalidDate     = invalidDate;
3947
proto$1.ordinal         = ordinal;
3948
proto$1.preparse        = preParsePostFormat;
3949
proto$1.postformat      = preParsePostFormat;
3950
proto$1.relativeTime    = relativeTime;
3951
proto$1.pastFuture      = pastFuture;
3952
proto$1.set             = set;
3953

    
3954
// Month
3955
proto$1.months            =        localeMonths;
3956
proto$1.monthsShort       =        localeMonthsShort;
3957
proto$1.monthsParse       =        localeMonthsParse;
3958
proto$1.monthsRegex       = monthsRegex;
3959
proto$1.monthsShortRegex  = monthsShortRegex;
3960

    
3961
// Week
3962
proto$1.week = localeWeek;
3963
proto$1.firstDayOfYear = localeFirstDayOfYear;
3964
proto$1.firstDayOfWeek = localeFirstDayOfWeek;
3965

    
3966
// Day of Week
3967
proto$1.weekdays       =        localeWeekdays;
3968
proto$1.weekdaysMin    =        localeWeekdaysMin;
3969
proto$1.weekdaysShort  =        localeWeekdaysShort;
3970
proto$1.weekdaysParse  =        localeWeekdaysParse;
3971

    
3972
proto$1.weekdaysRegex       =        weekdaysRegex;
3973
proto$1.weekdaysShortRegex  =        weekdaysShortRegex;
3974
proto$1.weekdaysMinRegex    =        weekdaysMinRegex;
3975

    
3976
// Hours
3977
proto$1.isPM = localeIsPM;
3978
proto$1.meridiem = localeMeridiem;
3979

    
3980
function get$1 (format, index, field, setter) {
3981
    var locale = getLocale();
3982
    var utc = createUTC().set(setter, index);
3983
    return locale[field](utc, format);
3984
}
3985

    
3986
function listMonthsImpl (format, index, field) {
3987
    if (isNumber(format)) {
3988
        index = format;
3989
        format = undefined;
3990
    }
3991

    
3992
    format = format || '';
3993

    
3994
    if (index != null) {
3995
        return get$1(format, index, field, 'month');
3996
    }
3997

    
3998
    var i;
3999
    var out = [];
4000
    for (i = 0; i < 12; i++) {
4001
        out[i] = get$1(format, i, field, 'month');
4002
    }
4003
    return out;
4004
}
4005

    
4006
// ()
4007
// (5)
4008
// (fmt, 5)
4009
// (fmt)
4010
// (true)
4011
// (true, 5)
4012
// (true, fmt, 5)
4013
// (true, fmt)
4014
function listWeekdaysImpl (localeSorted, format, index, field) {
4015
    if (typeof localeSorted === 'boolean') {
4016
        if (isNumber(format)) {
4017
            index = format;
4018
            format = undefined;
4019
        }
4020

    
4021
        format = format || '';
4022
    } else {
4023
        format = localeSorted;
4024
        index = format;
4025
        localeSorted = false;
4026

    
4027
        if (isNumber(format)) {
4028
            index = format;
4029
            format = undefined;
4030
        }
4031

    
4032
        format = format || '';
4033
    }
4034

    
4035
    var locale = getLocale(),
4036
        shift = localeSorted ? locale._week.dow : 0;
4037

    
4038
    if (index != null) {
4039
        return get$1(format, (index + shift) % 7, field, 'day');
4040
    }
4041

    
4042
    var i;
4043
    var out = [];
4044
    for (i = 0; i < 7; i++) {
4045
        out[i] = get$1(format, (i + shift) % 7, field, 'day');
4046
    }
4047
    return out;
4048
}
4049

    
4050
function listMonths (format, index) {
4051
    return listMonthsImpl(format, index, 'months');
4052
}
4053

    
4054
function listMonthsShort (format, index) {
4055
    return listMonthsImpl(format, index, 'monthsShort');
4056
}
4057

    
4058
function listWeekdays (localeSorted, format, index) {
4059
    return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
4060
}
4061

    
4062
function listWeekdaysShort (localeSorted, format, index) {
4063
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
4064
}
4065

    
4066
function listWeekdaysMin (localeSorted, format, index) {
4067
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
4068
}
4069

    
4070
getSetGlobalLocale('en', {
4071
    dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
4072
    ordinal : function (number) {
4073
        var b = number % 10,
4074
            output = (toInt(number % 100 / 10) === 1) ? 'th' :
4075
            (b === 1) ? 'st' :
4076
            (b === 2) ? 'nd' :
4077
            (b === 3) ? 'rd' : 'th';
4078
        return number + output;
4079
    }
4080
});
4081

    
4082
// Side effect imports
4083
hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
4084
hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
4085

    
4086
var mathAbs = Math.abs;
4087

    
4088
function abs () {
4089
    var data           = this._data;
4090

    
4091
    this._milliseconds = mathAbs(this._milliseconds);
4092
    this._days         = mathAbs(this._days);
4093
    this._months       = mathAbs(this._months);
4094

    
4095
    data.milliseconds  = mathAbs(data.milliseconds);
4096
    data.seconds       = mathAbs(data.seconds);
4097
    data.minutes       = mathAbs(data.minutes);
4098
    data.hours         = mathAbs(data.hours);
4099
    data.months        = mathAbs(data.months);
4100
    data.years         = mathAbs(data.years);
4101

    
4102
    return this;
4103
}
4104

    
4105
function addSubtract$1 (duration, input, value, direction) {
4106
    var other = createDuration(input, value);
4107

    
4108
    duration._milliseconds += direction * other._milliseconds;
4109
    duration._days         += direction * other._days;
4110
    duration._months       += direction * other._months;
4111

    
4112
    return duration._bubble();
4113
}
4114

    
4115
// supports only 2.0-style add(1, 's') or add(duration)
4116
function add$1 (input, value) {
4117
    return addSubtract$1(this, input, value, 1);
4118
}
4119

    
4120
// supports only 2.0-style subtract(1, 's') or subtract(duration)
4121
function subtract$1 (input, value) {
4122
    return addSubtract$1(this, input, value, -1);
4123
}
4124

    
4125
function absCeil (number) {
4126
    if (number < 0) {
4127
        return Math.floor(number);
4128
    } else {
4129
        return Math.ceil(number);
4130
    }
4131
}
4132

    
4133
function bubble () {
4134
    var milliseconds = this._milliseconds;
4135
    var days         = this._days;
4136
    var months       = this._months;
4137
    var data         = this._data;
4138
    var seconds, minutes, hours, years, monthsFromDays;
4139

    
4140
    // if we have a mix of positive and negative values, bubble down first
4141
    // check: https://github.com/moment/moment/issues/2166
4142
    if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
4143
            (milliseconds <= 0 && days <= 0 && months <= 0))) {
4144
        milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
4145
        days = 0;
4146
        months = 0;
4147
    }
4148

    
4149
    // The following code bubbles up values, see the tests for
4150
    // examples of what that means.
4151
    data.milliseconds = milliseconds % 1000;
4152

    
4153
    seconds           = absFloor(milliseconds / 1000);
4154
    data.seconds      = seconds % 60;
4155

    
4156
    minutes           = absFloor(seconds / 60);
4157
    data.minutes      = minutes % 60;
4158

    
4159
    hours             = absFloor(minutes / 60);
4160
    data.hours        = hours % 24;
4161

    
4162
    days += absFloor(hours / 24);
4163

    
4164
    // convert days to months
4165
    monthsFromDays = absFloor(daysToMonths(days));
4166
    months += monthsFromDays;
4167
    days -= absCeil(monthsToDays(monthsFromDays));
4168

    
4169
    // 12 months -> 1 year
4170
    years = absFloor(months / 12);
4171
    months %= 12;
4172

    
4173
    data.days   = days;
4174
    data.months = months;
4175
    data.years  = years;
4176

    
4177
    return this;
4178
}
4179

    
4180
function daysToMonths (days) {
4181
    // 400 years have 146097 days (taking into account leap year rules)
4182
    // 400 years have 12 months === 4800
4183
    return days * 4800 / 146097;
4184
}
4185

    
4186
function monthsToDays (months) {
4187
    // the reverse of daysToMonths
4188
    return months * 146097 / 4800;
4189
}
4190

    
4191
function as (units) {
4192
    if (!this.isValid()) {
4193
        return NaN;
4194
    }
4195
    var days;
4196
    var months;
4197
    var milliseconds = this._milliseconds;
4198

    
4199
    units = normalizeUnits(units);
4200

    
4201
    if (units === 'month' || units === 'year') {
4202
        days   = this._days   + milliseconds / 864e5;
4203
        months = this._months + daysToMonths(days);
4204
        return units === 'month' ? months : months / 12;
4205
    } else {
4206
        // handle milliseconds separately because of floating point math errors (issue #1867)
4207
        days = this._days + Math.round(monthsToDays(this._months));
4208
        switch (units) {
4209
            case 'week'   : return days / 7     + milliseconds / 6048e5;
4210
            case 'day'    : return days         + milliseconds / 864e5;
4211
            case 'hour'   : return days * 24    + milliseconds / 36e5;
4212
            case 'minute' : return days * 1440  + milliseconds / 6e4;
4213
            case 'second' : return days * 86400 + milliseconds / 1000;
4214
            // Math.floor prevents floating point math errors here
4215
            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
4216
            default: throw new Error('Unknown unit ' + units);
4217
        }
4218
    }
4219
}
4220

    
4221
// TODO: Use this.as('ms')?
4222
function valueOf$1 () {
4223
    if (!this.isValid()) {
4224
        return NaN;
4225
    }
4226
    return (
4227
        this._milliseconds +
4228
        this._days * 864e5 +
4229
        (this._months % 12) * 2592e6 +
4230
        toInt(this._months / 12) * 31536e6
4231
    );
4232
}
4233

    
4234
function makeAs (alias) {
4235
    return function () {
4236
        return this.as(alias);
4237
    };
4238
}
4239

    
4240
var asMilliseconds = makeAs('ms');
4241
var asSeconds      = makeAs('s');
4242
var asMinutes      = makeAs('m');
4243
var asHours        = makeAs('h');
4244
var asDays         = makeAs('d');
4245
var asWeeks        = makeAs('w');
4246
var asMonths       = makeAs('M');
4247
var asYears        = makeAs('y');
4248

    
4249
function clone$1 () {
4250
    return createDuration(this);
4251
}
4252

    
4253
function get$2 (units) {
4254
    units = normalizeUnits(units);
4255
    return this.isValid() ? this[units + 's']() : NaN;
4256
}
4257

    
4258
function makeGetter(name) {
4259
    return function () {
4260
        return this.isValid() ? this._data[name] : NaN;
4261
    };
4262
}
4263

    
4264
var milliseconds = makeGetter('milliseconds');
4265
var seconds      = makeGetter('seconds');
4266
var minutes      = makeGetter('minutes');
4267
var hours        = makeGetter('hours');
4268
var days         = makeGetter('days');
4269
var months       = makeGetter('months');
4270
var years        = makeGetter('years');
4271

    
4272
function weeks () {
4273
    return absFloor(this.days() / 7);
4274
}
4275

    
4276
var round = Math.round;
4277
var thresholds = {
4278
    ss: 44,         // a few seconds to seconds
4279
    s : 45,         // seconds to minute
4280
    m : 45,         // minutes to hour
4281
    h : 22,         // hours to day
4282
    d : 26,         // days to month
4283
    M : 11          // months to year
4284
};
4285

    
4286
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
4287
function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
4288
    return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
4289
}
4290

    
4291
function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
4292
    var duration = createDuration(posNegDuration).abs();
4293
    var seconds  = round(duration.as('s'));
4294
    var minutes  = round(duration.as('m'));
4295
    var hours    = round(duration.as('h'));
4296
    var days     = round(duration.as('d'));
4297
    var months   = round(duration.as('M'));
4298
    var years    = round(duration.as('y'));
4299

    
4300
    var a = seconds <= thresholds.ss && ['s', seconds]  ||
4301
            seconds < thresholds.s   && ['ss', seconds] ||
4302
            minutes <= 1             && ['m']           ||
4303
            minutes < thresholds.m   && ['mm', minutes] ||
4304
            hours   <= 1             && ['h']           ||
4305
            hours   < thresholds.h   && ['hh', hours]   ||
4306
            days    <= 1             && ['d']           ||
4307
            days    < thresholds.d   && ['dd', days]    ||
4308
            months  <= 1             && ['M']           ||
4309
            months  < thresholds.M   && ['MM', months]  ||
4310
            years   <= 1             && ['y']           || ['yy', years];
4311

    
4312
    a[2] = withoutSuffix;
4313
    a[3] = +posNegDuration > 0;
4314
    a[4] = locale;
4315
    return substituteTimeAgo.apply(null, a);
4316
}
4317

    
4318
// This function allows you to set the rounding function for relative time strings
4319
function getSetRelativeTimeRounding (roundingFunction) {
4320
    if (roundingFunction === undefined) {
4321
        return round;
4322
    }
4323
    if (typeof(roundingFunction) === 'function') {
4324
        round = roundingFunction;
4325
        return true;
4326
    }
4327
    return false;
4328
}
4329

    
4330
// This function allows you to set a threshold for relative time strings
4331
function getSetRelativeTimeThreshold (threshold, limit) {
4332
    if (thresholds[threshold] === undefined) {
4333
        return false;
4334
    }
4335
    if (limit === undefined) {
4336
        return thresholds[threshold];
4337
    }
4338
    thresholds[threshold] = limit;
4339
    if (threshold === 's') {
4340
        thresholds.ss = limit - 1;
4341
    }
4342
    return true;
4343
}
4344

    
4345
function humanize (withSuffix) {
4346
    if (!this.isValid()) {
4347
        return this.localeData().invalidDate();
4348
    }
4349

    
4350
    var locale = this.localeData();
4351
    var output = relativeTime$1(this, !withSuffix, locale);
4352

    
4353
    if (withSuffix) {
4354
        output = locale.pastFuture(+this, output);
4355
    }
4356

    
4357
    return locale.postformat(output);
4358
}
4359

    
4360
var abs$1 = Math.abs;
4361

    
4362
function sign(x) {
4363
    return ((x > 0) - (x < 0)) || +x;
4364
}
4365

    
4366
function toISOString$1() {
4367
    // for ISO strings we do not use the normal bubbling rules:
4368
    //  * milliseconds bubble up until they become hours
4369
    //  * days do not bubble at all
4370
    //  * months bubble up until they become years
4371
    // This is because there is no context-free conversion between hours and days
4372
    // (think of clock changes)
4373
    // and also not between days and months (28-31 days per month)
4374
    if (!this.isValid()) {
4375
        return this.localeData().invalidDate();
4376
    }
4377

    
4378
    var seconds = abs$1(this._milliseconds) / 1000;
4379
    var days         = abs$1(this._days);
4380
    var months       = abs$1(this._months);
4381
    var minutes, hours, years;
4382

    
4383
    // 3600 seconds -> 60 minutes -> 1 hour
4384
    minutes           = absFloor(seconds / 60);
4385
    hours             = absFloor(minutes / 60);
4386
    seconds %= 60;
4387
    minutes %= 60;
4388

    
4389
    // 12 months -> 1 year
4390
    years  = absFloor(months / 12);
4391
    months %= 12;
4392

    
4393

    
4394
    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
4395
    var Y = years;
4396
    var M = months;
4397
    var D = days;
4398
    var h = hours;
4399
    var m = minutes;
4400
    var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
4401
    var total = this.asSeconds();
4402

    
4403
    if (!total) {
4404
        // this is the same as C#'s (Noda) and python (isodate)...
4405
        // but not other JS (goog.date)
4406
        return 'P0D';
4407
    }
4408

    
4409
    var totalSign = total < 0 ? '-' : '';
4410
    var ymSign = sign(this._months) !== sign(total) ? '-' : '';
4411
    var daysSign = sign(this._days) !== sign(total) ? '-' : '';
4412
    var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
4413

    
4414
    return totalSign + 'P' +
4415
        (Y ? ymSign + Y + 'Y' : '') +
4416
        (M ? ymSign + M + 'M' : '') +
4417
        (D ? daysSign + D + 'D' : '') +
4418
        ((h || m || s) ? 'T' : '') +
4419
        (h ? hmsSign + h + 'H' : '') +
4420
        (m ? hmsSign + m + 'M' : '') +
4421
        (s ? hmsSign + s + 'S' : '');
4422
}
4423

    
4424
var proto$2 = Duration.prototype;
4425

    
4426
proto$2.isValid        = isValid$1;
4427
proto$2.abs            = abs;
4428
proto$2.add            = add$1;
4429
proto$2.subtract       = subtract$1;
4430
proto$2.as             = as;
4431
proto$2.asMilliseconds = asMilliseconds;
4432
proto$2.asSeconds      = asSeconds;
4433
proto$2.asMinutes      = asMinutes;
4434
proto$2.asHours        = asHours;
4435
proto$2.asDays         = asDays;
4436
proto$2.asWeeks        = asWeeks;
4437
proto$2.asMonths       = asMonths;
4438
proto$2.asYears        = asYears;
4439
proto$2.valueOf        = valueOf$1;
4440
proto$2._bubble        = bubble;
4441
proto$2.clone          = clone$1;
4442
proto$2.get            = get$2;
4443
proto$2.milliseconds   = milliseconds;
4444
proto$2.seconds        = seconds;
4445
proto$2.minutes        = minutes;
4446
proto$2.hours          = hours;
4447
proto$2.days           = days;
4448
proto$2.weeks          = weeks;
4449
proto$2.months         = months;
4450
proto$2.years          = years;
4451
proto$2.humanize       = humanize;
4452
proto$2.toISOString    = toISOString$1;
4453
proto$2.toString       = toISOString$1;
4454
proto$2.toJSON         = toISOString$1;
4455
proto$2.locale         = locale;
4456
proto$2.localeData     = localeData;
4457

    
4458
// Deprecations
4459
proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
4460
proto$2.lang = lang;
4461

    
4462
// Side effect imports
4463

    
4464
// FORMATTING
4465

    
4466
addFormatToken('X', 0, 0, 'unix');
4467
addFormatToken('x', 0, 0, 'valueOf');
4468

    
4469
// PARSING
4470

    
4471
addRegexToken('x', matchSigned);
4472
addRegexToken('X', matchTimestamp);
4473
addParseToken('X', function (input, array, config) {
4474
    config._d = new Date(parseFloat(input, 10) * 1000);
4475
});
4476
addParseToken('x', function (input, array, config) {
4477
    config._d = new Date(toInt(input));
4478
});
4479

    
4480
// Side effect imports
4481

    
4482

    
4483
hooks.version = '2.19.4';
4484

    
4485
setHookCallback(createLocal);
4486

    
4487
hooks.fn                    = proto;
4488
hooks.min                   = min;
4489
hooks.max                   = max;
4490
hooks.now                   = now;
4491
hooks.utc                   = createUTC;
4492
hooks.unix                  = createUnix;
4493
hooks.months                = listMonths;
4494
hooks.isDate                = isDate;
4495
hooks.locale                = getSetGlobalLocale;
4496
hooks.invalid               = createInvalid;
4497
hooks.duration              = createDuration;
4498
hooks.isMoment              = isMoment;
4499
hooks.weekdays              = listWeekdays;
4500
hooks.parseZone             = createInZone;
4501
hooks.localeData            = getLocale;
4502
hooks.isDuration            = isDuration;
4503
hooks.monthsShort           = listMonthsShort;
4504
hooks.weekdaysMin           = listWeekdaysMin;
4505
hooks.defineLocale          = defineLocale;
4506
hooks.updateLocale          = updateLocale;
4507
hooks.locales               = listLocales;
4508
hooks.weekdaysShort         = listWeekdaysShort;
4509
hooks.normalizeUnits        = normalizeUnits;
4510
hooks.relativeTimeRounding  = getSetRelativeTimeRounding;
4511
hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
4512
hooks.calendarFormat        = getCalendarFormat;
4513
hooks.prototype             = proto;
4514

    
4515
return hooks;
4516

    
4517
})));
클립보드 이미지 추가 (최대 크기: 500 MB)