function hooks() {
    return hookCallback.apply(null, arguments);
}n/a
ISO_8601 = function () {}n/a
RFC_2822 = function () {}n/a
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) {
    // 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';
    var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
    return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
}
function clone () {
...createFromInputFallback = function () {
    if (hooks.deprecationHandler != null) {
        hooks.deprecationHandler(null, msg);
    }
    if (firstTime) {
        var args = [];
        var arg;
        for (var i = 0; i < arguments.length; i++) {
            arg = '';
            if (typeof arguments[i] === 'object') {
                arg += '\n[' + i + '] ';
                for (var key in arguments[0]) {
                    arg += key + ': ' + arguments[0][key] + ', ';
                }
                arg = arg.slice(0, -2); // Remove trailing comma and space
            } else {
                arg = arguments[i];
            }
            args.push(arg);
        }
        warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
        firstTime = false;
    }
    return fn.apply(this, arguments);
}...
    if (config._isValid === false) {
        delete config._isValid;
    } else {
        return;
    }
    // Final attempt, use Input Fallback
    hooks.createFromInputFallback(config);
}
hooks.createFromInputFallback = deprecate(
    'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
    'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
    'discouraged and will be removed in an upcoming major release. Please refer to ' +
    'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
...function defineLocale(name, config) {
    if (config !== null) {
        var locale, parentConfig = baseConfig;
        config.abbr = name;
        if (locales[name] != null) {
            deprecateSimple('defineLocaleOverride',
                    'use moment.updateLocale(localeName, config) to change ' +
                    'an existing locale. moment.defineLocale(localeName, ' +
                    'config) should only be used for creating a new locale ' +
                    'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
            parentConfig = locales[name]._config;
        } else if (config.parentLocale != null) {
            if (locales[config.parentLocale] != null) {
                parentConfig = locales[config.parentLocale]._config;
            } else {
                locale = loadLocale(config.parentLocale);
                if (locale != null) {
                    parentConfig = locale._config;
                } else {
                    if (!localeFamilies[config.parentLocale]) {
                        localeFamilies[config.parentLocale] = [];
                    }
                    localeFamilies[config.parentLocale].push({
                        name: name,
                        config: config
                    });
                    return null;
                }
            }
        }
        locales[name] = new Locale(mergeConfigs(parentConfig, config));
        if (localeFamilies[name]) {
            localeFamilies[name].forEach(function (x) {
                defineLocale(x.name, x.config);
            });
        }
        // backwards compat for now: also set the locale
        // make sure we set the locale AFTER all child locales have been
        // created, so we won't end up with the child locale set.
        getSetGlobalLocale(name);
        return locales[name];
    } else {
        // useful for testing
        delete locales[name];
        return null;
    }
}...
    function defineLocale (name, config) {
if (config !== null) {
    var locale, parentConfig = baseConfig;
    config.abbr = name;
    if (locales[name] != null) {
        deprecateSimple('defineLocaleOverride',
                'use moment.updateLocale(localeName, config) to change ' +
                'an existing locale. moment.defineLocale(localeName, ' +
                'config) should only be used for creating a new locale ' +
                'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
        parentConfig = locales[name]._config;
    } else if (config.parentLocale != null) {
        if (locales[config.parentLocale] != null) {
            parentConfig = locales[config.parentLocale]._config;
        } else {
...function createDuration(input, key) {
    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
        };
    } else if (isNumber(input)) {
        duration = {};
        if (key) {
            duration[key] = input;
        } else {
            duration.milliseconds = input;
        }
    } else if (!!(match = aspNetRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : 1;
        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
        };
    } else if (!!(match = isoRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
        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)
        };
    } else if (duration == null) {// checks for null or undefined
        duration = {};
    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
        duration = {};
        duration.ms = diffRes.milliseconds;
        duration.M = diffRes.months;
    }
    ret = new Duration(duration);
    if (isDuration(input) && hasOwnProp(input, '_locale')) {
        ret._locale = input._locale;
    }
    return ret;
}...
Changed language ordinal method to return the number + ordinal instead of just the ordinal.
Changed two digit year parsing cutoff to match strptime.
Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.
Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`.
Removed the lang data objects from the top level namespace.
Duplicate `Date` passed to `moment()` instead of referencing it.
### 1.7.2 [See discussion](https://github.com/timrwood/moment/issues/456)
...function createInvalid(flags) {
    var m = createUTC(NaN);
    if (flags != null) {
        extend(getParsingFlags(m), flags);
    }
    else {
        getParsingFlags(m).userInvalidated = true;
    }
    return m;
}...
 * 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 () {
    if (!this.isValid()) {
        return 'moment.invalid(/* ' + this._i + ' */)';
    }
    var func = 'moment';
    var zone = '';
    if (!this.isLocal()) {
        func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
        zone = 'Z';
    }
...function isDate(input) {
    return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
}n/a
function isDuration(obj) {
    return obj instanceof Duration;
}n/a
function isMoment(obj) {
    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
}n/a
lang = function () {
    if (hooks.deprecationHandler != null) {
        hooks.deprecationHandler(null, msg);
    }
    if (firstTime) {
        var args = [];
        var arg;
        for (var i = 0; i < arguments.length; i++) {
            arg = '';
            if (typeof arguments[i] === 'object') {
                arg += '\n[' + i + '] ';
                for (var key in arguments[0]) {
                    arg += key + ': ' + arguments[0][key] + ', ';
                }
                arg = arg.slice(0, -2); // Remove trailing comma and space
            } else {
                arg = arguments[i];
            }
            args.push(arg);
        }
        warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
        firstTime = false;
    }
    return fn.apply(this, arguments);
}...
* [#1804](https://github.com/moment/moment/issues/1804) spanish del -> de
* [#1800](https://github.com/moment/moment/issues/1800) korean LT improvement
### 2.8.1
- Release August 1, 2014
* bugfix [#1813](https://github.com/moment/moment/issues/1813): fix moment().lang([key
]) incompatibility
### 2.8.0 [See changelog](https://gist.github.com/ichernev/ac3899324a5fa6c8c9b4)
- Release July 31, 2014
* incompatible changes
* [#1761](https://github.com/moment/moment/issues/1761): moments created without a language are no longer following the global language
, in case it changes. Only newly created moments take the global language by default. In case you're affected by this, wait
, comment on [#1797](https://github.com/moment/moment/issues/1797) and wait for a proper reimplementation
...langData = function () {
    if (hooks.deprecationHandler != null) {
        hooks.deprecationHandler(null, msg);
    }
    if (firstTime) {
        var args = [];
        var arg;
        for (var i = 0; i < arguments.length; i++) {
            arg = '';
            if (typeof arguments[i] === 'object') {
                arg += '\n[' + i + '] ';
                for (var key in arguments[0]) {
                    arg += key + ': ' + arguments[0][key] + ', ';
                }
                arg = arg.slice(0, -2); // Remove trailing comma and space
            } else {
                arg = arguments[i];
            }
            args.push(arg);
        }
        warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
        firstTime = false;
    }
    return fn.apply(this, arguments);
}n/a
function getSetGlobalLocale(key, values) {
    var data;
    if (key) {
        if (isUndefined(values)) {
            data = getLocale(key);
        }
        else {
            data = defineLocale(key, values);
        }
        if (data) {
            // moment.duration._locale = moment._locale = data;
            globalLocale = data;
        }
        else {
            if ((typeof console !==  'undefined') && console.warn) {
                //warn user if arguments are passed but the locale could not be set
                console.warn('Locale ' + key +  ' not found. Did you forget to load it?');
            }
        }
    }
    return globalLocale._abbr;
}...
    return -(wholeMonthDiff + adjust) || 0;
}
hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
function toString () {
    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;
...function getLocale(key) {
    var locale;
    if (key && key._locale && key._locale._abbr) {
        key = key._locale._abbr;
    }
    if (!key) {
        return globalLocale;
    }
    if (!isArray(key)) {
        //short-circuit everything else
        locale = loadLocale(key);
        if (locale) {
            return locale;
        }
        key = [key];
    }
    return chooseLocale(key);
}...
    if (padded) {
        formatTokenFunctions[padded[0]] = function () {
            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
        };
    }
    if (ordinal) {
        formatTokenFunctions[ordinal] = function () {
            return this.localeData().ordinal(func.apply(this, arguments), token);
        };
    }
}
function removeFormattingTokens(input) {
    if (input.match(/\[[\s\S]/)) {
        return input.replace(/^\[|\]$/g, '');
...function listLocales() {
    return keys(locales);
}n/a
function max() {
    var args = [].slice.call(arguments, 0);
    return pickBy('isAfter', args);
}...
}
function zeroFill(number, targetLength, forceSign) {
    var absNumber = '' + Math.abs(number),
        zerosToFill = targetLength - absNumber.length,
        sign = number >= 0;
    return (sign ? (forceSign ? '+' : '') : '-') +
        Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
}
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;
var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
var formatFunctions = {};
...function min() {
    var args = [].slice.call(arguments, 0);
    return pickBy('isBefore', args);
}...
    }
    return value;
}
// compare two arrays, return the number of differences
function compareArrays(array1, array2, dontConvert) {
    var len = Math.min(array1.length, array2.length),
        lengthDiff = Math.abs(array1.length - array2.length),
        diffs = 0,
        i;
    for (i = 0; i < len; i++) {
        if ((dontConvert && array1[i] !== array2[i]) ||
            (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
            diffs++;
...function listMonths(format, index) {
    return listMonthsImpl(format, index, 'months');
}...
});
addFormatToken('MMM', 0, 0, function (format) {
    return this.localeData().monthsShort(this, format);
});
addFormatToken('MMMM', 0, 0, function (format) {
    return this.localeData().months(this, format);
});
// ALIASES
addUnitAlias('month', 'M');
// PRIORITY
...function listMonthsShort(format, index) {
    return listMonthsImpl(format, index, 'monthsShort');
}...
// FORMATTING
addFormatToken('M', ['MM', 2], 'Mo', function () {
    return this.month() + 1;
});
addFormatToken('MMM', 0, 0, function (format) {
    return this.localeData().monthsShort(this, format);
});
addFormatToken('MMMM', 0, 0, function (format) {
    return this.localeData().months(this, format);
});
// ALIASES
...function normalizeUnits(units) {
    return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
}n/a
now = function () {
    return Date.now ? Date.now() : +(new Date());
}...
Bugfix for [issue 5](https://github.com/timrwood/underscore.date/pull/5).
### 0.5.0
- Release Jun 13, 2011
Dropped the redundant `_date.date()` in favor of `_date()`.
Removed `_date.now()`, as it is a duplicate of `_date()` with no parameters.
Removed `_date.isLeapYear(yearNumber)`. Use `_date([yearNumber]).isLeapYear()` instead.
Exposed customization options through the `_date.relativeTime`, `_date.weekdays`, `_date.weekdaysShort`, `_date.months`, `_date.
monthsShort`, and `_date.ordinal` variables instead of the `_date.customize()` function.
### 0.4.1
- Release May 9, 2011
...parseTwoDigitYear = function (input) {
    return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
}...
addRegexToken('YY',     match1to2, match2);
addRegexToken('YYYY',   match1to4, match4);
addRegexToken('YYYYY',  match1to6, match6);
addRegexToken('YYYYYY', match1to6, match6);
addParseToken(['YYYYY', 'YYYYYY'], YEAR);
addParseToken('YYYY', function (input, array) {
    array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
});
addParseToken('YY', function (input, array) {
    array[YEAR] = hooks.parseTwoDigitYear(input);
});
addParseToken('Y', function (input, array) {
    array[YEAR] = parseInt(input, 10);
});
...function createInZone() {
    return createLocal.apply(null, arguments).parseZone();
}...
proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more
 information', isDaylightSavingTimeShifted);
function createUnix (input) {
    return createLocal(input * 1000);
}
function createInZone () {
    return createLocal.apply(null, arguments).parseZone();
}
function preParsePostFormat (string) {
    return string;
}
var proto$1 = Locale.prototype;
...function getSetRelativeTimeRounding(roundingFunction) {
    if (roundingFunction === undefined) {
        return round;
    }
    if (typeof(roundingFunction) === 'function') {
        round = roundingFunction;
        return true;
    }
    return false;
}n/a
function getSetRelativeTimeThreshold(threshold, limit) {
    if (thresholds[threshold] === undefined) {
        return false;
    }
    if (limit === undefined) {
        return thresholds[threshold];
    }
    thresholds[threshold] = limit;
    if (threshold === 's') {
        thresholds.ss = limit - 1;
    }
    return true;
}n/a
function createUnix(input) {
    return createLocal(input * 1000);
}n/a
function updateLocale(name, config) {
    if (config != null) {
        var locale, tmpLocale, parentConfig = baseConfig;
        // MERGE
        tmpLocale = loadLocale(name);
        if (tmpLocale != null) {
            parentConfig = tmpLocale._config;
        }
        config = mergeConfigs(parentConfig, config);
        locale = new Locale(config);
        locale.parentLocale = locales[name];
        locales[name] = locale;
        // backwards compat for now: also set the locale
        getSetGlobalLocale(name);
    } else {
        // pass null for config to unupdate, useful for tests
        if (locales[name] != null) {
            if (locales[name].parentLocale != null) {
                locales[name] = locales[name].parentLocale;
            } else if (locales[name] != null) {
                delete locales[name];
            }
        }
    }
    return locales[name];
}...
    function defineLocale (name, config) {
if (config !== null) {
    var locale, parentConfig = baseConfig;
    config.abbr = name;
    if (locales[name] != null) {
        deprecateSimple('defineLocaleOverride',
                'use moment.updateLocale(localeName, config) to change ' +
                'an existing locale. moment.defineLocale(localeName, ' +
                'config) should only be used for creating a new locale ' +
                'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
        parentConfig = locales[name]._config;
    } else if (config.parentLocale != null) {
        if (locales[config.parentLocale] != null) {
            parentConfig = locales[config.parentLocale]._config;
...updateOffset = function () {}...
    if (!this.isValid()) {
        this._d = new Date(NaN);
    }
    // Prevent infinite loop in case updateOffset creates new moment
    // objects.
    if (updateInProgress === false) {
        updateInProgress = true;
        hooks.updateOffset(this);
        updateInProgress = false;
    }
}
function isMoment (obj) {
    return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
}
...function createUTC(input, format, locale, strict) {
    return createLocalOrUTC(input, format, locale, strict, true).utc();
}...
Added `moment#toJSON`
Bugfix: Fixed parsing of first century dates
Bugfix: Parsing 10Sep2001 should work as expected
Bugfix: Fixed weirdness with `moment.utc()` parsing.
Changed language ordinal method to return the number + ordinal instead of just the ordinal.
Changed two digit year parsing cutoff to match strptime.
Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.
...function listWeekdays(localeSorted, format, index) {
    return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
}...
});
addFormatToken('ddd', 0, 0, function (format) {
    return this.localeData().weekdaysShort(this, format);
});
addFormatToken('dddd', 0, 0, function (format) {
    return this.localeData().weekdays(this, format);
});
addFormatToken('e', 0, 0, 'weekday');
addFormatToken('E', 0, 0, 'isoWeekday');
// ALIASES
...function listWeekdaysMin(localeSorted, format, index) {
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
}...
}
// FORMATTING
addFormatToken('d', 0, 'do', 'day');
addFormatToken('dd', 0, 0, function (format) {
    return this.localeData().weekdaysMin(this, format);
});
addFormatToken('ddd', 0, 0, function (format) {
    return this.localeData().weekdaysShort(this, format);
});
addFormatToken('dddd', 0, 0, function (format) {
...function listWeekdaysShort(localeSorted, format, index) {
    return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
}...
addFormatToken('d', 0, 'do', 'day');
addFormatToken('dd', 0, 0, function (format) {
    return this.localeData().weekdaysMin(this, format);
});
addFormatToken('ddd', 0, 0, function (format) {
    return this.localeData().weekdaysShort(this, format);
});
addFormatToken('dddd', 0, 0, function (format) {
    return this.localeData().weekdays(this, format);
});
addFormatToken('e', 0, 0, 'weekday');
...function createDuration(input, key) {
    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
        };
    } else if (isNumber(input)) {
        duration = {};
        if (key) {
            duration[key] = input;
        } else {
            duration.milliseconds = input;
        }
    } else if (!!(match = aspNetRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : 1;
        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
        };
    } else if (!!(match = isoRegex.exec(input))) {
        sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
        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)
        };
    } else if (duration == null) {// checks for null or undefined
        duration = {};
    } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
        diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
        duration = {};
        duration.ms = diffRes.milliseconds;
        duration.M = diffRes.months;
    }
    ret = new Duration(duration);
    if (isDuration(input) && hasOwnProp(input, '_locale')) {
        ret._locale = input._locale;
    }
    return ret;
}...
Changed language ordinal method to return the number + ordinal instead of just the ordinal.
Changed two digit year parsing cutoff to match strptime.
Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.
Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`.
Removed the lang data objects from the top level namespace.
Duplicate `Date` passed to `moment()` instead of referencing it.
### 1.7.2 [See discussion](https://github.com/timrwood/moment/issues/456)
...function createInvalid$1() {
    return createDuration(NaN);
}...
 * 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 () {
    if (!this.isValid()) {
        return 'moment.invalid(/* ' + this._i + ' */)';
    }
    var func = 'moment';
    var zone = '';
    if (!this.isLocal()) {
        func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
        zone = 'Z';
    }
...function bubble() {
    var milliseconds = this._milliseconds;
    var days         = this._days;
    var months       = this._months;
    var data         = this._data;
    var seconds, minutes, hours, years, monthsFromDays;
    // if we have a mix of positive and negative values, bubble down first
    // check: https://github.com/moment/moment/issues/2166
    if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
            (milliseconds <= 0 && days <= 0 && months <= 0))) {
        milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
        days = 0;
        months = 0;
    }
    // The following code bubbles up values, see the tests for
    // examples of what that means.
    data.milliseconds = milliseconds % 1000;
    seconds           = absFloor(milliseconds / 1000);
    data.seconds      = seconds % 60;
    minutes           = absFloor(seconds / 60);
    data.minutes      = minutes % 60;
    hours             = absFloor(minutes / 60);
    data.hours        = hours % 24;
    days += absFloor(hours / 24);
    // convert days to months
    monthsFromDays = absFloor(daysToMonths(days));
    months += monthsFromDays;
    days -= absCeil(monthsToDays(monthsFromDays));
    // 12 months -> 1 year
    years = absFloor(months / 12);
    months %= 12;
    data.days   = days;
    data.months = months;
    data.years  = years;
    return this;
}...
        quarters * 3 +
        years * 12;
    this._data = {};
    this._locale = getLocale();
    this._bubble();
}
function isDuration (obj) {
    return obj instanceof Duration;
}
function absRound (number) {
...function abs() {
    var data           = this._data;
    this._milliseconds = mathAbs(this._milliseconds);
    this._days         = mathAbs(this._days);
    this._months       = mathAbs(this._months);
    data.milliseconds  = mathAbs(data.milliseconds);
    data.seconds       = mathAbs(data.seconds);
    data.minutes       = mathAbs(data.minutes);
    data.hours         = mathAbs(data.hours);
    data.months        = mathAbs(data.months);
    data.years         = mathAbs(data.years);
    return this;
}...
    return value;
}
// compare two arrays, return the number of differences
function compareArrays(array1, array2, dontConvert) {
    var len = Math.min(array1.length, array2.length),
        lengthDiff = Math.abs(array1.length - array2.length),
        diffs = 0,
        i;
    for (i = 0; i < len; i++) {
        if ((dontConvert && array1[i] !== array2[i]) ||
            (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
            diffs++;
        }
...function add$1(input, value) {
    return addSubtract$1(this, input, value, 1);
}...
### 1.0.0
- Release
Added convenience methods for getting and setting date parts.
Added better support for `moment.add()`.
Added better lang support in NodeJS.
Renamed library from underscore.date to Moment.js
### 0.6.1
...function as(units) {
    if (!this.isValid()) {
        return NaN;
    }
    var days;
    var months;
    var milliseconds = this._milliseconds;
    units = normalizeUnits(units);
    if (units === 'month' || units === 'year') {
        days   = this._days   + milliseconds / 864e5;
        months = this._months + daysToMonths(days);
        return units === 'month' ? months : months / 12;
    } else {
        // handle milliseconds separately because of floating point math errors (issue #1867)
        days = this._days + Math.round(monthsToDays(this._months));
        switch (units) {
            case 'week'   : return days / 7     + milliseconds / 6048e5;
            case 'day'    : return days         + milliseconds / 864e5;
            case 'hour'   : return days * 24    + milliseconds / 36e5;
            case 'minute' : return days * 1440  + milliseconds / 6e4;
            case 'second' : return days * 86400 + milliseconds / 1000;
            // Math.floor prevents floating point math errors here
            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
            default: throw new Error('Unknown unit ' + units);
        }
    }
}...
            // Math.floor prevents floating point math errors here
            case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
            default: throw new Error('Unknown unit ' + units);
        }
    }
}
// TODO: Use this.as('ms')?
function valueOf$1 () {
    if (!this.isValid()) {
        return NaN;
    }
    return (
        this._milliseconds +
        this._days * 864e5 +
...asDays = function () {
    return this.as(alias);
}n/a
asHours = function () {
    return this.as(alias);
}n/a
asMilliseconds = function () {
    return this.as(alias);
}n/a
asMinutes = function () {
    return this.as(alias);
}n/a
asMonths = function () {
    return this.as(alias);
}n/a
asSeconds = function () {
    return this.as(alias);
}...
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
var Y = years;
var M = months;
var D = days;
var h = hours;
var m = minutes;
var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
var total = this.asSeconds();
if (!total) {
    // this is the same as C#'s (Noda) and python (isodate)...
    // but not other JS (goog.date)
    return 'P0D';
}
...asWeeks = function () {
    return this.as(alias);
}n/a
asYears = function () {
    return this.as(alias);
}n/a
function clone$1() {
    return createDuration(this);
}...
  [#4213](https://github.com/moment/moment/issues/4213)
## Features
* [#3735](https://github.com/moment/moment/pull/3735) [feature] Ignore NaN values in setters
* [#4106](https://github.com/moment/moment/pull/4106) [fixup] Drop isNumeric utility fn, fixes [#3735](https://github.com/moment
/moment/issues/3735)
* [#4080](https://github.com/moment/moment/pull/4080) [feature] Implement a clone method for durations, fixes [#4078](https://github
.com/moment/moment/issues/4078)
* [#4215](https://github.com/moment/moment/pull/4215) [misc] TS: Add duration.clone(),
for [#4080](https://github.com/moment/moment/issues/4080)
## Packaging
* [#4003](https://github.com/moment/moment/pull/4003) [pkg] bower: Remove tests from package
* [#3904](https://github.com/moment/moment/pull/3904) [pkg] jsnext:main -> module in package.json
* [#4060](https://github.com/moment/moment/pull/4060) [pkg] Account for new rollup interface
...days = function () {
    return this.isValid() ? this._data[name] : NaN;
}...
var minutes      = makeGetter('minutes');
var hours        = makeGetter('hours');
var days         = makeGetter('days');
var months       = makeGetter('months');
var years        = makeGetter('years');
function weeks () {
    return absFloor(this.days() / 7);
}
var round = Math.round;
var thresholds = {
    ss: 44,         // a few seconds to seconds
    s : 45,         // seconds to minute
    m : 45,         // minutes to hour
...function get$2(units) {
    units = normalizeUnits(units);
    return this.isValid() ? this[units + 's']() : NaN;
}n/a
hours = function () {
    return this.isValid() ? this._data[name] : NaN;
}...
    this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
    this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
}
// FORMATTING
function hFormat() {
    return this.hours() % 12 || 12;
}
function kFormat() {
    return this.hours() || 24;
}
addFormatToken('H', ['HH', 2], 0, 'hour');
...function humanize(withSuffix) {
    if (!this.isValid()) {
        return this.localeData().invalidDate();
    }
    var locale = this.localeData();
    var output = relativeTime$1(this, !withSuffix, locale);
    if (withSuffix) {
        output = locale.pastFuture(+this, output);
    }
    return locale.postformat(output);
}...
Changed language ordinal method to return the number + ordinal instead of just the ordinal.
Changed two digit year parsing cutoff to match strptime.
Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.
Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`.
Removed the lang data objects from the top level namespace.
Duplicate `Date` passed to `moment()` instead of referencing it.
### 1.7.2 [See discussion](https://github.com/timrwood/moment/issues/456)
...function isValid$1() {
    return this._isValid;
}...
### 1.7.0 [See discussion](https://github.com/timrwood/moment/issues/288)
- Release Jul 26, 2012
Added `moment.fn.endOf()` and `moment.fn.startOf()`.
Added validation via `moment.fn.isValid()`.
Made formatting method 3x faster. http://jsperf.com/momentjs-cached-format-functions
Add support for month/weekday callbacks in `moment.fn.format()`
Added instance specific languages.
...lang = function () {
    if (hooks.deprecationHandler != null) {
        hooks.deprecationHandler(null, msg);
    }
    if (firstTime) {
        var args = [];
        var arg;
        for (var i = 0; i < arguments.length; i++) {
            arg = '';
            if (typeof arguments[i] === 'object') {
                arg += '\n[' + i + '] ';
                for (var key in arguments[0]) {
                    arg += key + ': ' + arguments[0][key] + ', ';
                }
                arg = arg.slice(0, -2); // Remove trailing comma and space
            } else {
                arg = arguments[i];
            }
            args.push(arg);
        }
        warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
        firstTime = false;
    }
    return fn.apply(this, arguments);
}...
* [#1804](https://github.com/moment/moment/issues/1804) spanish del -> de
* [#1800](https://github.com/moment/moment/issues/1800) korean LT improvement
### 2.8.1
- Release August 1, 2014
* bugfix [#1813](https://github.com/moment/moment/issues/1813): fix moment().lang([key
]) incompatibility
### 2.8.0 [See changelog](https://gist.github.com/ichernev/ac3899324a5fa6c8c9b4)
- Release July 31, 2014
* incompatible changes
* [#1761](https://github.com/moment/moment/issues/1761): moments created without a language are no longer following the global language
, in case it changes. Only newly created moments take the global language by default. In case you're affected by this, wait
, comment on [#1797](https://github.com/moment/moment/issues/1797) and wait for a proper reimplementation
...function locale(key) {
    var newLocaleData;
    if (key === undefined) {
        return this._locale._abbr;
    } else {
        newLocaleData = getLocale(key);
        if (newLocaleData != null) {
            this._locale = newLocaleData;
        }
        return this;
    }
}...
    return -(wholeMonthDiff + adjust) || 0;
}
hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
function toString () {
    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;
...function localeData() {
    return this._locale;
}...
    if (padded) {
        formatTokenFunctions[padded[0]] = function () {
            return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
        };
    }
    if (ordinal) {
        formatTokenFunctions[ordinal] = function () {
            return this.localeData().ordinal(func.apply(this, arguments), token);
        };
    }
}
function removeFormattingTokens(input) {
    if (input.match(/\[[\s\S]/)) {
        return input.replace(/^\[|\]$/g, '');
...milliseconds = function () {
    return this.isValid() ? this._data[name] : NaN;
}...
    case 'hour':
        this.minutes(0);
        /* falls through */
    case 'minute':
        this.seconds(0);
        /* falls through */
    case 'second':
        this.milliseconds(0);
}
// weeks are a special case
if (units === 'week') {
    this.weekday(0);
}
if (units === 'isoWeek') {
...minutes = function () {
    return this.isValid() ? this._data[name] : NaN;
}...
}
addFormatToken('H', ['HH', 2], 0, 'hour');
addFormatToken('h', ['hh', 2], 0, hFormat);
addFormatToken('k', ['kk', 2], 0, kFormat);
addFormatToken('hmm', 0, 0, function () {
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
});
addFormatToken('hmmss', 0, 0, function () {
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
        zeroFill(this.seconds(), 2);
});
...months = function () {
    return this.isValid() ? this._data[name] : NaN;
}...
});
addFormatToken('MMM', 0, 0, function (format) {
    return this.localeData().monthsShort(this, format);
});
addFormatToken('MMMM', 0, 0, function (format) {
    return this.localeData().months(this, format);
});
// ALIASES
addUnitAlias('month', 'M');
// PRIORITY
...seconds = function () {
    return this.isValid() ? this._data[name] : NaN;
}...
addFormatToken('hmm', 0, 0, function () {
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
});
addFormatToken('hmmss', 0, 0, function () {
    return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
        zeroFill(this.seconds(), 2);
});
addFormatToken('Hmm', 0, 0, function () {
    return '' + this.hours() + zeroFill(this.minutes(), 2);
});
addFormatToken('Hmmss', 0, 0, function () {
...function subtract$1(input, value) {
    return addSubtract$1(this, input, value, -1);
}...
function setOffsetToLocal (keepLocalTime) {
    if (this._isUTC) {
        this.utcOffset(0, keepLocalTime);
        this._isUTC = false;
        if (keepLocalTime) {
            this.subtract(getDateOffset(this), 'm');
        }
    }
    return this;
}
function setOffsetToParsedOffset () {
    if (this._tzm != null) {
...function toISOString$1() {
    // for ISO strings we do not use the normal bubbling rules:
    //  * milliseconds bubble up until they become hours
    //  * days do not bubble at all
    //  * months bubble up until they become years
    // This is because there is no context-free conversion between hours and days
    // (think of clock changes)
    // and also not between days and months (28-31 days per month)
    if (!this.isValid()) {
        return this.localeData().invalidDate();
    }
    var seconds = abs$1(this._milliseconds) / 1000;
    var days         = abs$1(this._days);
    var months       = abs$1(this._months);
    var minutes, hours, years;
    // 3600 seconds -> 60 minutes -> 1 hour
    minutes           = absFloor(seconds / 60);
    hours             = absFloor(minutes / 60);
    seconds %= 60;
    minutes %= 60;
    // 12 months -> 1 year
    years  = absFloor(months / 12);
    months %= 12;
    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
    var Y = years;
    var M = months;
    var D = days;
    var h = hours;
    var m = minutes;
    var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
    var total = this.asSeconds();
    if (!total) {
        // this is the same as C#'s (Noda) and python (isodate)...
        // but not other JS (goog.date)
        return 'P0D';
    }
    var totalSign = total < 0 ? '-' : '';
    var ymSign = sign(this._months) !== sign(total) ? '-' : '';
    var daysSign = sign(this._days) !== sign(total) ? '-' : '';
    var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
    return totalSign + 'P' +
        (Y ? ymSign + Y + 'Y' : '') +
        (M ? ymSign + M + 'M' : '') +
        (D ? daysSign + D + 'D' : '') +
        ((h || m || s) ? 'T' : '') +
        (h ? hmsSign + h + 'H' : '') +
        (m ? hmsSign + m + 'M' : '') +
        (s ? hmsSign + s + 'S' : '');
}...
    var m = utc ? this.clone().utc() : this;
    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');
    }
    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, &
apos;Z'));
        }
    }
    return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
}
...toIsoString = function () {
    if (hooks.deprecationHandler != null) {
        hooks.deprecationHandler(null, msg);
    }
    if (firstTime) {
        var args = [];
        var arg;
        for (var i = 0; i < arguments.length; i++) {
            arg = '';
            if (typeof arguments[i] === 'object') {
                arg += '\n[' + i + '] ';
                for (var key in arguments[0]) {
                    arg += key + ': ' + arguments[0][key] + ', ';
                }
                arg = arg.slice(0, -2); // Remove trailing comma and space
            } else {
                arg = arguments[i];
            }
            args.push(arg);
        }
        warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
        firstTime = false;
    }
    return fn.apply(this, arguments);
}n/a
function toISOString$1() {
    // for ISO strings we do not use the normal bubbling rules:
    //  * milliseconds bubble up until they become hours
    //  * days do not bubble at all
    //  * months bubble up until they become years
    // This is because there is no context-free conversion between hours and days
    // (think of clock changes)
    // and also not between days and months (28-31 days per month)
    if (!this.isValid()) {
        return this.localeData().invalidDate();
    }
    var seconds = abs$1(this._milliseconds) / 1000;
    var days         = abs$1(this._days);
    var months       = abs$1(this._months);
    var minutes, hours, years;
    // 3600 seconds -> 60 minutes -> 1 hour
    minutes           = absFloor(seconds / 60);
    hours             = absFloor(minutes / 60);
    seconds %= 60;
    minutes %= 60;
    // 12 months -> 1 year
    years  = absFloor(months / 12);
    months %= 12;
    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
    var Y = years;
    var M = months;
    var D = days;
    var h = hours;
    var m = minutes;
    var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
    var total = this.asSeconds();
    if (!total) {
        // this is the same as C#'s (Noda) and python (isodate)...
        // but not other JS (goog.date)
        return 'P0D';
    }
    var totalSign = total < 0 ? '-' : '';
    var ymSign = sign(this._months) !== sign(total) ? '-' : '';
    var daysSign = sign(this._days) !== sign(total) ? '-' : '';
    var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
    return totalSign + 'P' +
        (Y ? ymSign + Y + 'Y' : '') +
        (M ? ymSign + M + 'M' : '') +
        (D ? daysSign + D + 'D' : '') +
        ((h || m || s) ? 'T' : '') +
        (h ? hmsSign + h + 'H' : '') +
        (m ? hmsSign + m + 'M' : '') +
        (s ? hmsSign + s + 'S' : '');
}...
        minutes: m.minutes(),
        seconds: m.seconds(),
        milliseconds: m.milliseconds()
    };
}
function toJSON () {
    // new Date(NaN).toJSON() === null
    return this.isValid() ? this.toISOString() : null;
}
function isValid$2 () {
    return isValid(this);
}
...function toISOString$1() {
    // for ISO strings we do not use the normal bubbling rules:
    //  * milliseconds bubble up until they become hours
    //  * days do not bubble at all
    //  * months bubble up until they become years
    // This is because there is no context-free conversion between hours and days
    // (think of clock changes)
    // and also not between days and months (28-31 days per month)
    if (!this.isValid()) {
        return this.localeData().invalidDate();
    }
    var seconds = abs$1(this._milliseconds) / 1000;
    var days         = abs$1(this._days);
    var months       = abs$1(this._months);
    var minutes, hours, years;
    // 3600 seconds -> 60 minutes -> 1 hour
    minutes           = absFloor(seconds / 60);
    hours             = absFloor(minutes / 60);
    seconds %= 60;
    minutes %= 60;
    // 12 months -> 1 year
    years  = absFloor(months / 12);
    months %= 12;
    // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
    var Y = years;
    var M = months;
    var D = days;
    var h = hours;
    var m = minutes;
    var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
    var total = this.asSeconds();
    if (!total) {
        // this is the same as C#'s (Noda) and python (isodate)...
        // but not other JS (goog.date)
        return 'P0D';
    }
    var totalSign = total < 0 ? '-' : '';
    var ymSign = sign(this._months) !== sign(total) ? '-' : '';
    var daysSign = sign(this._days) !== sign(total) ? '-' : '';
    var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
    return totalSign + 'P' +
        (Y ? ymSign + Y + 'Y' : '') +
        (M ? ymSign + M + 'M' : '') +
        (D ? daysSign + D + 'D' : '') +
        ((h || m || s) ? 'T' : '') +
        (h ? hmsSign + h + 'H' : '') +
        (m ? hmsSign + m + 'M' : '') +
        (s ? hmsSign + s + 'S' : '');
}...
}
function zeroFill(number, targetLength, forceSign) {
    var absNumber = '' + Math.abs(number),
        zerosToFill = targetLength - absNumber.length,
        sign = number >= 0;
    return (sign ? (forceSign ? '+' : '') : '-') +
        Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
}
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;
var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
var formatFunctions = {};
...function valueOf$1() {
    if (!this.isValid()) {
        return NaN;
    }
    return (
        this._milliseconds +
        this._days * 864e5 +
        (this._months % 12) * 2592e6 +
        toInt(this._months / 12) * 31536e6
    );
}...
## Bugfixes
* [#3109](https://github.com/moment/moment/pull/3109) Fix [#1756](https://github.com/moment/moment/issues/1756) Resolved thread-
safe issue on server side.
* [#3078](https://github.com/moment/moment/pull/3078) Fix parsing for months/weekdays with weird characters
* [#3098](https://github.com/moment/moment/pull/3098) Use Z suffix when in UTC mode ([#3020](https://github.com/moment/moment/issues
/3020))
* [#2995](https://github.com/moment/moment/pull/2995) Fix floating point rounding errors in durations
* [#3059](https://github.com/moment/moment/pull/3059) fix bug where diff returns -0 in month-related diffs
* [#3045](https://github.com/moment/moment/pull/3045) Fix mistaking any input for 'a' token
* [#2877](https://github.com/moment/moment/pull/2877) Use explicit .valueOf() calls instead
 of coercion
* [#3036](https://github.com/moment/moment/pull/3036) Year setter should keep time when DST changes
Plus 3 new locales and locale fixes.
### 2.12.0 [See full changelog](https://gist.github.com/ichernev/6e5bfdf8d6522fc4ac73)
- Release March 7, 2016
...function weeks() {
    return absFloor(this.days() / 7);
}n/a
years = function () {
    return this.isValid() ? this._data[name] : NaN;
}n/a