Skip to content
Snippets Groups Projects
index.js 7.33 MiB
Newer Older
  • Learn to ignore specific revisions
  • Romain CREY's avatar
    Romain CREY committed
        // FORMATTING
    
    
        function offset(token, separator) {
    
    Romain CREY's avatar
    Romain CREY committed
            addFormatToken(token, 0, 0, function () {
    
                var offset = this.utcOffset(),
                    sign = '+';
    
    Romain CREY's avatar
    Romain CREY committed
                if (offset < 0) {
                    offset = -offset;
                    sign = '-';
                }
    
                return (
                    sign +
                    zeroFill(~~(offset / 60), 2) +
                    separator +
                    zeroFill(~~offset % 60, 2)
                );
    
    Romain CREY's avatar
    Romain CREY committed
            });
        }
    
        offset('Z', ':');
        offset('ZZ', '');
    
        // PARSING
    
    
        addRegexToken('Z', matchShortOffset);
    
    Romain CREY's avatar
    Romain CREY committed
        addRegexToken('ZZ', matchShortOffset);
        addParseToken(['Z', 'ZZ'], function (input, array, config) {
            config._useUTC = true;
            config._tzm = offsetFromString(matchShortOffset, input);
        });
    
        // HELPERS
    
        // timezone chunker
        // '+10:00' > ['10',  '00']
        // '-1530'  > ['-15', '30']
        var chunkOffset = /([\+\-]|\d\d)/gi;
    
        function offsetFromString(matcher, string) {
    
            var matches = (string || '').match(matcher),
                chunk,
                parts,
                minutes;
    
    Romain CREY's avatar
    Romain CREY committed
    
            if (matches === null) {
                return null;
            }
    
    
            chunk = matches[matches.length - 1] || [];
            parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
            minutes = +(parts[1] * 60) + toInt(parts[2]);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
        // Return a moment from input, that is local/utc/zone equivalent to model.
        function cloneWithOffset(input, model) {
            var res, diff;
            if (model._isUTC) {
                res = model.clone();
    
                diff =
                    (isMoment(input) || isDate(input)
                        ? input.valueOf()
                        : createLocal(input).valueOf()) - res.valueOf();
    
    Romain CREY's avatar
    Romain CREY committed
                // Use low-level api, because this fn is low-level api.
                res._d.setTime(res._d.valueOf() + diff);
                hooks.updateOffset(res, false);
                return res;
            } else {
                return createLocal(input).local();
            }
        }
    
    
        function getDateOffset(m) {
    
    Romain CREY's avatar
    Romain CREY committed
            // On Firefox.24 Date#getTimezoneOffset returns a floating point.
            // https://github.com/moment/moment/pull/1871
    
            return -Math.round(m._d.getTimezoneOffset());
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
        // HOOKS
    
        // This function will be called whenever a moment is mutated.
        // It is intended to keep the offset in sync with the timezone.
        hooks.updateOffset = function () {};
    
        // MOMENTS
    
        // keepLocalTime = true means only change the timezone, without
        // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
        // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
        // +0200, so we adjust the time as needed, to be valid.
        //
        // Keeping the time actually adds/subtracts (one hour)
        // from the actual represented time. That is why we call updateOffset
        // a second time. In case it wants us to change the offset again
        // _changeInProgress == true case, then we have to adjust, because
        // there is no such time in the given timezone.
    
        function getSetOffset(input, keepLocalTime, keepMinutes) {
    
    Romain CREY's avatar
    Romain CREY committed
            var offset = this._offset || 0,
                localAdjust;
            if (!this.isValid()) {
                return input != null ? this : NaN;
            }
            if (input != null) {
                if (typeof input === 'string') {
                    input = offsetFromString(matchShortOffset, input);
                    if (input === null) {
                        return this;
                    }
                } else if (Math.abs(input) < 16 && !keepMinutes) {
                    input = input * 60;
                }
                if (!this._isUTC && keepLocalTime) {
                    localAdjust = getDateOffset(this);
                }
                this._offset = input;
                this._isUTC = true;
                if (localAdjust != null) {
                    this.add(localAdjust, 'm');
                }
                if (offset !== input) {
                    if (!keepLocalTime || this._changeInProgress) {
    
                        addSubtract(
                            this,
                            createDuration(input - offset, 'm'),
                            1,
                            false
                        );
    
    Romain CREY's avatar
    Romain CREY committed
                    } else if (!this._changeInProgress) {
                        this._changeInProgress = true;
                        hooks.updateOffset(this, true);
                        this._changeInProgress = null;
                    }
                }
                return this;
            } else {
                return this._isUTC ? offset : getDateOffset(this);
            }
        }
    
    
        function getSetZone(input, keepLocalTime) {
    
    Romain CREY's avatar
    Romain CREY committed
            if (input != null) {
                if (typeof input !== 'string') {
                    input = -input;
                }
    
                this.utcOffset(input, keepLocalTime);
    
                return this;
            } else {
                return -this.utcOffset();
            }
        }
    
    
        function setOffsetToUTC(keepLocalTime) {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.utcOffset(0, keepLocalTime);
        }
    
    
        function setOffsetToLocal(keepLocalTime) {
    
    Romain CREY's avatar
    Romain CREY committed
            if (this._isUTC) {
                this.utcOffset(0, keepLocalTime);
                this._isUTC = false;
    
                if (keepLocalTime) {
                    this.subtract(getDateOffset(this), 'm');
                }
            }
            return this;
        }
    
    
        function setOffsetToParsedOffset() {
    
    Romain CREY's avatar
    Romain CREY committed
            if (this._tzm != null) {
                this.utcOffset(this._tzm, false, true);
            } else if (typeof this._i === 'string') {
                var tZone = offsetFromString(matchOffset, this._i);
                if (tZone != null) {
                    this.utcOffset(tZone);
    
                } else {
    
    Romain CREY's avatar
    Romain CREY committed
                    this.utcOffset(0, true);
                }
            }
            return this;
        }
    
    
        function hasAlignedHourOffset(input) {
    
    Romain CREY's avatar
    Romain CREY committed
            if (!this.isValid()) {
                return false;
            }
            input = input ? createLocal(input).utcOffset() : 0;
    
            return (this.utcOffset() - input) % 60 === 0;
        }
    
    
        function isDaylightSavingTime() {
    
    Romain CREY's avatar
    Romain CREY committed
            return (
                this.utcOffset() > this.clone().month(0).utcOffset() ||
                this.utcOffset() > this.clone().month(5).utcOffset()
            );
        }
    
    
        function isDaylightSavingTimeShifted() {
    
    Romain CREY's avatar
    Romain CREY committed
            if (!isUndefined(this._isDSTShifted)) {
                return this._isDSTShifted;
            }
    
    
            var c = {},
                other;
    
    Romain CREY's avatar
    Romain CREY committed
    
            copyConfig(c, this);
            c = prepareConfig(c);
    
            if (c._a) {
    
                other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
                this._isDSTShifted =
                    this.isValid() && compareArrays(c._a, other.toArray()) > 0;
    
    Romain CREY's avatar
    Romain CREY committed
            } else {
                this._isDSTShifted = false;
            }
    
            return this._isDSTShifted;
        }
    
    
        function isLocal() {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.isValid() ? !this._isUTC : false;
        }
    
    
        function isUtcOffset() {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.isValid() ? this._isUTC : false;
        }
    
    
        function isUtc() {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.isValid() ? this._isUTC && this._offset === 0 : false;
        }
    
        // ASP.NET json date format regex
    
        var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,
            // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
            // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
            // and further modified to allow for strings containing both week and day
            isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function createDuration(input, key) {
    
    Romain CREY's avatar
    Romain CREY committed
            var duration = input,
                // matching against regexp is expensive, do it on demand
                match = null,
                sign,
                ret,
                diffRes;
    
            if (isDuration(input)) {
                duration = {
    
                    ms: input._milliseconds,
                    d: input._days,
                    M: input._months,
    
    Romain CREY's avatar
    Romain CREY committed
                };
    
            } else if (isNumber(input) || !isNaN(+input)) {
    
    Romain CREY's avatar
    Romain CREY committed
                duration = {};
                if (key) {
    
                    duration[key] = +input;
    
    Romain CREY's avatar
    Romain CREY committed
                } else {
    
                    duration.milliseconds = +input;
    
    Romain CREY's avatar
    Romain CREY committed
                }
    
            } else if ((match = aspNetRegex.exec(input))) {
                sign = match[1] === '-' ? -1 : 1;
    
    Romain CREY's avatar
    Romain CREY committed
                duration = {
    
                    y: 0,
                    d: toInt(match[DATE]) * sign,
                    h: toInt(match[HOUR]) * sign,
                    m: toInt(match[MINUTE]) * sign,
                    s: toInt(match[SECOND]) * sign,
                    ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match
    
    Romain CREY's avatar
    Romain CREY committed
                };
    
            } else if ((match = isoRegex.exec(input))) {
                sign = match[1] === '-' ? -1 : 1;
    
    Romain CREY's avatar
    Romain CREY committed
                duration = {
    
                    y: parseIso(match[2], sign),
                    M: parseIso(match[3], sign),
                    w: parseIso(match[4], sign),
                    d: parseIso(match[5], sign),
                    h: parseIso(match[6], sign),
                    m: parseIso(match[7], sign),
                    s: parseIso(match[8], sign),
    
    Romain CREY's avatar
    Romain CREY committed
                };
    
            } else if (duration == null) {
                // checks for null or undefined
    
    Romain CREY's avatar
    Romain CREY committed
                duration = {};
    
            } else if (
                typeof duration === 'object' &&
                ('from' in duration || 'to' in duration)
            ) {
                diffRes = momentsDifference(
                    createLocal(duration.from),
                    createLocal(duration.to)
                );
    
    Romain CREY's avatar
    Romain CREY committed
    
                duration = {};
                duration.ms = diffRes.milliseconds;
                duration.M = diffRes.months;
            }
    
            ret = new Duration(duration);
    
            if (isDuration(input) && hasOwnProp(input, '_locale')) {
                ret._locale = input._locale;
            }
    
    
            if (isDuration(input) && hasOwnProp(input, '_isValid')) {
                ret._isValid = input._isValid;
            }
    
    
    Romain CREY's avatar
    Romain CREY committed
            return ret;
        }
    
        createDuration.fn = Duration.prototype;
        createDuration.invalid = createInvalid$1;
    
    
        function parseIso(inp, sign) {
    
    Romain CREY's avatar
    Romain CREY committed
            // We'd normally use ~~inp for this, but unfortunately it also
            // converts floats to ints.
            // inp may be undefined, so careful calling replace on it.
            var res = inp && parseFloat(inp.replace(',', '.'));
            // apply sign while we're at it
            return (isNaN(res) ? 0 : res) * sign;
        }
    
        function positiveMomentsDifference(base, other) {
            var res = {};
    
    
            res.months =
                other.month() - base.month() + (other.year() - base.year()) * 12;
    
    Romain CREY's avatar
    Romain CREY committed
            if (base.clone().add(res.months, 'M').isAfter(other)) {
                --res.months;
            }
    
    
            res.milliseconds = +other - +base.clone().add(res.months, 'M');
    
    Romain CREY's avatar
    Romain CREY committed
    
            return res;
        }
    
        function momentsDifference(base, other) {
            var res;
            if (!(base.isValid() && other.isValid())) {
    
                return { milliseconds: 0, months: 0 };
    
    Romain CREY's avatar
    Romain CREY committed
            }
    
            other = cloneWithOffset(other, base);
            if (base.isBefore(other)) {
                res = positiveMomentsDifference(base, other);
            } else {
                res = positiveMomentsDifference(other, base);
                res.milliseconds = -res.milliseconds;
                res.months = -res.months;
            }
    
            return res;
        }
    
        // TODO: remove 'name' arg after deprecation is removed
        function createAdder(direction, name) {
            return function (val, period) {
                var dur, tmp;
                //invert the arguments, but complain about it
                if (period !== null && !isNaN(+period)) {
    
                    deprecateSimple(
                        name,
                        'moment().' +
                            name +
                            '(period, number) is deprecated. Please use moment().' +
                            name +
                            '(number, period). ' +
                            'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'
                    );
                    tmp = val;
                    val = period;
                    period = tmp;
    
    Romain CREY's avatar
    Romain CREY committed
                }
    
                dur = createDuration(val, period);
                addSubtract(this, dur, direction);
                return this;
            };
        }
    
    
        function addSubtract(mom, duration, isAdding, updateOffset) {
    
    Romain CREY's avatar
    Romain CREY committed
            var milliseconds = duration._milliseconds,
                days = absRound(duration._days),
                months = absRound(duration._months);
    
            if (!mom.isValid()) {
                // No op
                return;
            }
    
            updateOffset = updateOffset == null ? true : updateOffset;
    
            if (months) {
                setMonth(mom, get(mom, 'Month') + months * isAdding);
            }
            if (days) {
                set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
            }
            if (milliseconds) {
                mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
            }
            if (updateOffset) {
                hooks.updateOffset(mom, days || months);
            }
        }
    
    
        var add = createAdder(1, 'add'),
            subtract = createAdder(-1, 'subtract');
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function isString(input) {
            return typeof input === 'string' || input instanceof String;
    
        // type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined
        function isMomentInput(input) {
            return (
                isMoment(input) ||
                isDate(input) ||
                isString(input) ||
                isNumber(input) ||
                isNumberOrStringArray(input) ||
                isMomentInputObject(input) ||
                input === null ||
                input === undefined
            );
        }
    
        function isMomentInputObject(input) {
            var objectTest = isObject(input) && !isObjectEmpty(input),
                propertyTest = false,
                properties = [
                    'years',
                    'year',
                    'y',
                    'months',
                    'month',
                    'M',
                    'days',
                    'day',
                    'd',
                    'dates',
                    'date',
                    'D',
                    'hours',
                    'hour',
                    'h',
                    'minutes',
                    'minute',
                    'm',
                    'seconds',
                    'second',
                    's',
                    'milliseconds',
                    'millisecond',
                    'ms',
                ],
                i,
                property;
    
            for (i = 0; i < properties.length; i += 1) {
                property = properties[i];
                propertyTest = propertyTest || hasOwnProp(input, property);
            }
    
            return objectTest && propertyTest;
        }
    
        function isNumberOrStringArray(input) {
            var arrayTest = isArray(input),
                dataTypeTest = false;
            if (arrayTest) {
                dataTypeTest =
                    input.filter(function (item) {
                        return !isNumber(item) && isString(input);
                    }).length === 0;
            }
            return arrayTest && dataTypeTest;
        }
    
        function isCalendarSpec(input) {
            var objectTest = isObject(input) && !isObjectEmpty(input),
                propertyTest = false,
                properties = [
                    'sameDay',
                    'nextDay',
                    'lastDay',
                    'nextWeek',
                    'lastWeek',
                    'sameElse',
                ],
                i,
                property;
    
            for (i = 0; i < properties.length; i += 1) {
                property = properties[i];
                propertyTest = propertyTest || hasOwnProp(input, property);
            }
    
            return objectTest && propertyTest;
        }
    
        function getCalendarFormat(myMoment, now) {
            var diff = myMoment.diff(now, 'days', true);
            return diff < -6
                ? 'sameElse'
                : diff < -1
                ? 'lastWeek'
                : diff < 0
                ? 'lastDay'
                : diff < 1
                ? 'sameDay'
                : diff < 2
                ? 'nextDay'
                : diff < 7
                ? 'nextWeek'
                : 'sameElse';
        }
    
        function calendar$1(time, formats) {
            // Support for single parameter, formats only overload to the calendar function
            if (arguments.length === 1) {
                if (!arguments[0]) {
                    time = undefined;
                    formats = undefined;
                } else if (isMomentInput(arguments[0])) {
                    time = arguments[0];
                    formats = undefined;
                } else if (isCalendarSpec(arguments[0])) {
                    formats = arguments[0];
                    time = undefined;
                }
            }
    
    Romain CREY's avatar
    Romain CREY committed
            // We want to compare the start of today, vs this.
            // Getting start-of-today depends on whether we're local/utc/offset or not.
            var now = time || createLocal(),
                sod = cloneWithOffset(now, this).startOf('day'),
    
                format = hooks.calendarFormat(this, sod) || 'sameElse',
                output =
                    formats &&
                    (isFunction(formats[format])
                        ? formats[format].call(this, now)
                        : formats[format]);
    
            return this.format(
                output || this.localeData().calendar(format, this, createLocal(now))
            );
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function clone() {
    
    Romain CREY's avatar
    Romain CREY committed
            return new Moment(this);
        }
    
    
        function isAfter(input, units) {
    
    Romain CREY's avatar
    Romain CREY committed
            var localInput = isMoment(input) ? input : createLocal(input);
            if (!(this.isValid() && localInput.isValid())) {
                return false;
            }
            units = normalizeUnits(units) || 'millisecond';
            if (units === 'millisecond') {
                return this.valueOf() > localInput.valueOf();
            } else {
                return localInput.valueOf() < this.clone().startOf(units).valueOf();
            }
        }
    
    
        function isBefore(input, units) {
    
    Romain CREY's avatar
    Romain CREY committed
            var localInput = isMoment(input) ? input : createLocal(input);
            if (!(this.isValid() && localInput.isValid())) {
                return false;
            }
            units = normalizeUnits(units) || 'millisecond';
            if (units === 'millisecond') {
                return this.valueOf() < localInput.valueOf();
            } else {
                return this.clone().endOf(units).valueOf() < localInput.valueOf();
            }
        }
    
    
        function isBetween(from, to, units, inclusivity) {
    
    Romain CREY's avatar
    Romain CREY committed
            var localFrom = isMoment(from) ? from : createLocal(from),
                localTo = isMoment(to) ? to : createLocal(to);
            if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
                return false;
            }
            inclusivity = inclusivity || '()';
    
            return (
                (inclusivity[0] === '('
                    ? this.isAfter(localFrom, units)
                    : !this.isBefore(localFrom, units)) &&
                (inclusivity[1] === ')'
                    ? this.isBefore(localTo, units)
                    : !this.isAfter(localTo, units))
            );
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function isSame(input, units) {
    
    Romain CREY's avatar
    Romain CREY committed
            var localInput = isMoment(input) ? input : createLocal(input),
                inputMs;
            if (!(this.isValid() && localInput.isValid())) {
                return false;
            }
            units = normalizeUnits(units) || 'millisecond';
            if (units === 'millisecond') {
                return this.valueOf() === localInput.valueOf();
            } else {
                inputMs = localInput.valueOf();
    
                return (
                    this.clone().startOf(units).valueOf() <= inputMs &&
                    inputMs <= this.clone().endOf(units).valueOf()
                );
    
        function isSameOrAfter(input, units) {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.isSame(input, units) || this.isAfter(input, units);
        }
    
    
        function isSameOrBefore(input, units) {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.isSame(input, units) || this.isBefore(input, units);
        }
    
    
        function diff(input, units, asFloat) {
            var that, zoneDelta, output;
    
    Romain CREY's avatar
    Romain CREY committed
    
            if (!this.isValid()) {
                return NaN;
            }
    
            that = cloneWithOffset(input, this);
    
            if (!that.isValid()) {
                return NaN;
            }
    
            zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
    
            units = normalizeUnits(units);
    
            switch (units) {
    
                case 'year':
                    output = monthDiff(this, that) / 12;
                    break;
                case 'month':
                    output = monthDiff(this, that);
                    break;
                case 'quarter':
                    output = monthDiff(this, that) / 3;
                    break;
                case 'second':
                    output = (this - that) / 1e3;
                    break; // 1000
                case 'minute':
                    output = (this - that) / 6e4;
                    break; // 1000 * 60
                case 'hour':
                    output = (this - that) / 36e5;
                    break; // 1000 * 60 * 60
                case 'day':
                    output = (this - that - zoneDelta) / 864e5;
                    break; // 1000 * 60 * 60 * 24, negate dst
                case 'week':
                    output = (this - that - zoneDelta) / 6048e5;
                    break; // 1000 * 60 * 60 * 24 * 7, negate dst
                default:
                    output = this - that;
    
    Romain CREY's avatar
    Romain CREY committed
            }
    
            return asFloat ? output : absFloor(output);
        }
    
    
        function monthDiff(a, b) {
            if (a.date() < b.date()) {
                // end-of-month calculations work correct when the start month has more
                // days than the end month.
                return -monthDiff(b, a);
            }
    
    Romain CREY's avatar
    Romain CREY committed
            // difference in months
    
            var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
    
    Romain CREY's avatar
    Romain CREY committed
                // b is in (anchor - 1 month, anchor + 1 month)
                anchor = a.clone().add(wholeMonthDiff, 'months'),
    
                anchor2,
                adjust;
    
    Romain CREY's avatar
    Romain CREY committed
    
            if (b - anchor < 0) {
                anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
                // linear across the month
                adjust = (b - anchor) / (anchor - anchor2);
            } else {
                anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
                // linear across the month
                adjust = (b - anchor) / (anchor2 - anchor);
            }
    
            //check for negative zero, return zero if negative zero
            return -(wholeMonthDiff + adjust) || 0;
        }
    
        hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
        hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
    
    
        function toString() {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
        }
    
        function toISOString(keepOffset) {
            if (!this.isValid()) {
                return null;
            }
    
            var utc = keepOffset !== true,
                m = utc ? this.clone().utc() : this;
    
    Romain CREY's avatar
    Romain CREY committed
            if (m.year() < 0 || m.year() > 9999) {
    
                return formatMoment(
                    m,
                    utc
                        ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'
                        : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'
                );
    
    Romain CREY's avatar
    Romain CREY committed
            }
            if (isFunction(Date.prototype.toISOString)) {
                // native implementation is ~50x faster, use it when we can
                if (utc) {
                    return this.toDate().toISOString();
                } else {
    
                    return new Date(this.valueOf() + this.utcOffset() * 60 * 1000)
                        .toISOString()
                        .replace('Z', formatMoment(m, 'Z'));
    
    Romain CREY's avatar
    Romain CREY committed
                }
            }
    
            return formatMoment(
                m,
                utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'
            );
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
        /**
         * Return a human readable representation of a moment that can
         * also be evaluated to get a new moment which is the same
         *
         * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
         */
    
        function inspect() {
    
    Romain CREY's avatar
    Romain CREY committed
            if (!this.isValid()) {
                return 'moment.invalid(/* ' + this._i + ' */)';
            }
    
            var func = 'moment',
                zone = '',
                prefix,
                year,
                datetime,
                suffix;
    
    Romain CREY's avatar
    Romain CREY committed
            if (!this.isLocal()) {
                func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
                zone = 'Z';
            }
    
            prefix = '[' + func + '("]';
            year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
            datetime = '-MM-DD[T]HH:mm:ss.SSS';
            suffix = zone + '[")]';
    
    Romain CREY's avatar
    Romain CREY committed
    
            return this.format(prefix + year + datetime + suffix);
        }
    
    
        function format(inputString) {
    
    Romain CREY's avatar
    Romain CREY committed
            if (!inputString) {
    
                inputString = this.isUtc()
                    ? hooks.defaultFormatUtc
                    : hooks.defaultFormat;
    
    Romain CREY's avatar
    Romain CREY committed
            }
            var output = formatMoment(this, inputString);
            return this.localeData().postformat(output);
        }
    
    
        function from(time, withoutSuffix) {
            if (
                this.isValid() &&
                ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
            ) {
                return createDuration({ to: this, from: time })
                    .locale(this.locale())
                    .humanize(!withoutSuffix);
    
    Romain CREY's avatar
    Romain CREY committed
            } else {
                return this.localeData().invalidDate();
            }
        }
    
    
        function fromNow(withoutSuffix) {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.from(createLocal(), withoutSuffix);
        }
    
    
        function to(time, withoutSuffix) {
            if (
                this.isValid() &&
                ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
            ) {
                return createDuration({ from: this, to: time })
                    .locale(this.locale())
                    .humanize(!withoutSuffix);
    
    Romain CREY's avatar
    Romain CREY committed
            } else {
                return this.localeData().invalidDate();
            }
        }
    
    
        function toNow(withoutSuffix) {
    
    Romain CREY's avatar
    Romain CREY committed
            return this.to(createLocal(), withoutSuffix);
        }
    
        // If passed a locale key, it will set the locale for this
        // instance.  Otherwise, it will return the locale configuration
        // variables for this instance.
    
        function locale(key) {
    
    Romain CREY's avatar
    Romain CREY committed
            var newLocaleData;
    
            if (key === undefined) {
                return this._locale._abbr;
            } else {
                newLocaleData = getLocale(key);
                if (newLocaleData != null) {
                    this._locale = newLocaleData;
                }
                return this;
            }
        }
    
        var lang = deprecate(
            'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
            function (key) {
                if (key === undefined) {
                    return this.localeData();
                } else {
                    return this.locale(key);
                }
            }
        );
    
    
        function localeData() {
    
    Romain CREY's avatar
    Romain CREY committed
            return this._locale;
        }
    
    
        var MS_PER_SECOND = 1000,
            MS_PER_MINUTE = 60 * MS_PER_SECOND,
            MS_PER_HOUR = 60 * MS_PER_MINUTE,
            MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
    
    Romain CREY's avatar
    Romain CREY committed
    
        // actual modulo - handles negative numbers (for dates before 1970):
        function mod$1(dividend, divisor) {
    
            return ((dividend % divisor) + divisor) % divisor;
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
        function localStartOfDate(y, m, d) {
            // the date constructor remaps years 0-99 to 1900-1999
            if (y < 100 && y >= 0) {
                // preserve leap years using a full 400 year cycle, then reset
                return new Date(y + 400, m, d) - MS_PER_400_YEARS;
            } else {
                return new Date(y, m, d).valueOf();
            }
        }
    
        function utcStartOfDate(y, m, d) {
            // Date.UTC remaps years 0-99 to 1900-1999
            if (y < 100 && y >= 0) {
                // preserve leap years using a full 400 year cycle, then reset
                return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
            } else {
                return Date.UTC(y, m, d);
            }
        }
    
    
        function startOf(units) {
            var time, startOfDate;
    
    Romain CREY's avatar
    Romain CREY committed
            units = normalizeUnits(units);
            if (units === undefined || units === 'millisecond' || !this.isValid()) {
                return this;
            }
    
    
            startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
    
    Romain CREY's avatar
    Romain CREY committed
    
            switch (units) {
                case 'year':
                    time = startOfDate(this.year(), 0, 1);
                    break;
                case 'quarter':
    
                    time = startOfDate(
                        this.year(),
                        this.month() - (this.month() % 3),
                        1
                    );
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'month':
                    time = startOfDate(this.year(), this.month(), 1);
                    break;
                case 'week':
    
                    time = startOfDate(
                        this.year(),
                        this.month(),
                        this.date() - this.weekday()
                    );
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'isoWeek':
    
                    time = startOfDate(
                        this.year(),
                        this.month(),
                        this.date() - (this.isoWeekday() - 1)
                    );
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'day':
                case 'date':
                    time = startOfDate(this.year(), this.month(), this.date());
                    break;
                case 'hour':
                    time = this._d.valueOf();
    
                    time -= mod$1(
                        time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
                        MS_PER_HOUR
                    );
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'minute':
                    time = this._d.valueOf();
                    time -= mod$1(time, MS_PER_MINUTE);
                    break;
                case 'second':
                    time = this._d.valueOf();
                    time -= mod$1(time, MS_PER_SECOND);
                    break;
            }
    
            this._d.setTime(time);
            hooks.updateOffset(this, true);
            return this;
        }
    
    
        function endOf(units) {
            var time, startOfDate;
    
    Romain CREY's avatar
    Romain CREY committed
            units = normalizeUnits(units);
            if (units === undefined || units === 'millisecond' || !this.isValid()) {
                return this;
            }
    
    
            startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
    
    Romain CREY's avatar
    Romain CREY committed
    
            switch (units) {
                case 'year':
                    time = startOfDate(this.year() + 1, 0, 1) - 1;
                    break;
                case 'quarter':
    
                    time =
                        startOfDate(
                            this.year(),
                            this.month() - (this.month() % 3) + 3,
                            1
                        ) - 1;
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'month':
                    time = startOfDate(this.year(), this.month() + 1, 1) - 1;
                    break;
                case 'week':
    
                    time =
                        startOfDate(
                            this.year(),
                            this.month(),
                            this.date() - this.weekday() + 7
                        ) - 1;
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'isoWeek':
    
                    time =
                        startOfDate(
                            this.year(),
                            this.month(),
                            this.date() - (this.isoWeekday() - 1) + 7
                        ) - 1;
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'day':
                case 'date':
                    time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
                    break;
                case 'hour':
                    time = this._d.valueOf();
    
                    time +=
                        MS_PER_HOUR -
                        mod$1(
                            time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
                            MS_PER_HOUR
                        ) -
                        1;
    
    Romain CREY's avatar
    Romain CREY committed
                    break;
                case 'minute':
                    time = this._d.valueOf();
                    time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
                    break;
                case 'second':
                    time = this._d.valueOf();
                    time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
                    break;
            }
    
            this._d.setTime(time);
            hooks.updateOffset(this, true);