Skip to content
Snippets Groups Projects
index.js 8.75 MiB
Newer Older
  • Learn to ignore specific revisions
  •                         '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));
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                if (localeFamilies[name]) {
                    localeFamilies[name].forEach(function (x) {
                        defineLocale(x.name, x.config);
                    });
                }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                // 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);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                return locales[name];
            } else {
                // useful for testing
                delete locales[name];
                return null;
            }
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function updateLocale(name, config) {
            if (config != null) {
                var locale,
                    tmpLocale,
                    parentConfig = baseConfig;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                if (locales[name] != null && locales[name].parentLocale != null) {
                    // Update existing child locale in-place to avoid memory-leaks
                    locales[name].set(mergeConfigs(locales[name]._config, config));
                } else {
                    // MERGE
                    tmpLocale = loadLocale(name);
                    if (tmpLocale != null) {
                        parentConfig = tmpLocale._config;
                    }
                    config = mergeConfigs(parentConfig, config);
                    if (tmpLocale == null) {
                        // updateLocale is called for creating a new locale
                        // Set abbr so it will have a name (getters return
                        // undefined otherwise).
                        config.abbr = name;
                    }
                    locale = new Locale(config);
                    locale.parentLocale = locales[name];
                    locales[name] = locale;
                }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                // 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;
                        if (name === getSetGlobalLocale()) {
                            getSetGlobalLocale(name);
                        }
                    } else if (locales[name] != null) {
                        delete locales[name];
                    }
                }
            }
            return locales[name];
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // returns locale data
        function getLocale(key) {
            var locale;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (key && key._locale && key._locale._abbr) {
                key = key._locale._abbr;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (!key) {
                return globalLocale;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (!isArray(key)) {
                //short-circuit everything else
                locale = loadLocale(key);
                if (locale) {
                    return locale;
                }
                key = [key];
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            return chooseLocale(key);
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function listLocales() {
            return keys(locales);
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function checkOverflow(m) {
            var overflow,
                a = m._a;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (a && getParsingFlags(m).overflow === -2) {
                overflow =
                    a[MONTH] < 0 || a[MONTH] > 11
                        ? MONTH
                        : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH])
                        ? DATE
                        : a[HOUR] < 0 ||
                          a[HOUR] > 24 ||
                          (a[HOUR] === 24 &&
                              (a[MINUTE] !== 0 ||
                                  a[SECOND] !== 0 ||
                                  a[MILLISECOND] !== 0))
                        ? HOUR
                        : a[MINUTE] < 0 || a[MINUTE] > 59
                        ? MINUTE
                        : a[SECOND] < 0 || a[SECOND] > 59
                        ? SECOND
                        : a[MILLISECOND] < 0 || a[MILLISECOND] > 999
                        ? MILLISECOND
                        : -1;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                if (
                    getParsingFlags(m)._overflowDayOfYear &&
                    (overflow < YEAR || overflow > DATE)
                ) {
                    overflow = DATE;
                }
                if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
                    overflow = WEEK;
                }
                if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
                    overflow = WEEKDAY;
                }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                getParsingFlags(m).overflow = overflow;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // iso 8601 regex
        // 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)
        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)?)?$/,
            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)?)?$/,
            tzRegex = /Z|[+-]\d\d(?::?\d\d)?/,
            isoDates = [
                ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
                ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
                ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
                ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
                ['YYYY-DDD', /\d{4}-\d{3}/],
                ['YYYY-MM', /\d{4}-\d\d/, false],
                ['YYYYYYMMDD', /[+-]\d{10}/],
                ['YYYYMMDD', /\d{8}/],
                ['GGGG[W]WWE', /\d{4}W\d{3}/],
                ['GGGG[W]WW', /\d{4}W\d{2}/, false],
                ['YYYYDDD', /\d{7}/],
                ['YYYYMM', /\d{6}/, false],
                ['YYYY', /\d{4}/, false],
            ],
            // iso time formats and regexes
            isoTimes = [
                ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
                ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
                ['HH:mm:ss', /\d\d:\d\d:\d\d/],
                ['HH:mm', /\d\d:\d\d/],
                ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
                ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
                ['HHmmss', /\d\d\d\d\d\d/],
                ['HHmm', /\d\d\d\d/],
                ['HH', /\d\d/],
            ],
            aspNetJsonRegex = /^\/?Date\((-?\d+)/i,
            // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
            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}))$/,
            obsOffsets = {
                UT: 0,
                GMT: 0,
                EDT: -4 * 60,
                EST: -5 * 60,
                CDT: -5 * 60,
                CST: -6 * 60,
                MDT: -6 * 60,
                MST: -7 * 60,
                PDT: -7 * 60,
                PST: -8 * 60,
            };
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // date from iso format
        function configFromISO(config) {
            var i,
                l,
                string = config._i,
                match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
                allowTime,
                dateFormat,
                timeFormat,
                tzFormat;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (match) {
                getParsingFlags(config).iso = true;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                for (i = 0, l = isoDates.length; i < l; i++) {
                    if (isoDates[i][1].exec(match[1])) {
                        dateFormat = isoDates[i][0];
                        allowTime = isoDates[i][2] !== false;
                        break;
                    }
                }
                if (dateFormat == null) {
                    config._isValid = false;
                    return;
                }
                if (match[3]) {
                    for (i = 0, l = isoTimes.length; i < l; i++) {
                        if (isoTimes[i][1].exec(match[3])) {
                            // match[2] should be 'T' or space
                            timeFormat = (match[2] || ' ') + isoTimes[i][0];
                            break;
                        }
                    }
                    if (timeFormat == null) {
                        config._isValid = false;
                        return;
                    }
                }
                if (!allowTime && timeFormat != null) {
                    config._isValid = false;
                    return;
                }
                if (match[4]) {
                    if (tzRegex.exec(match[4])) {
                        tzFormat = 'Z';
                    } else {
                        config._isValid = false;
                        return;
                    }
                }
                config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
                configFromStringAndFormat(config);
            } else {
                config._isValid = false;
            }
        }
    
        function extractFromRFC2822Strings(
            yearStr,
            monthStr,
            dayStr,
            hourStr,
            minuteStr,
            secondStr
        ) {
            var result = [
                untruncateYear(yearStr),
                defaultLocaleMonthsShort.indexOf(monthStr),
                parseInt(dayStr, 10),
                parseInt(hourStr, 10),
                parseInt(minuteStr, 10),
            ];
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (secondStr) {
                result.push(parseInt(secondStr, 10));
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function untruncateYear(yearStr) {
            var year = parseInt(yearStr, 10);
            if (year <= 49) {
                return 2000 + year;
            } else if (year <= 999) {
                return 1900 + year;
            }
            return year;
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function preprocessRFC2822(s) {
            // Remove comments and folding whitespace and replace multiple-spaces with a single space
            return s
                .replace(/\([^)]*\)|[\n\t]/g, ' ')
                .replace(/(\s\s+)/g, ' ')
                .replace(/^\s\s*/, '')
                .replace(/\s\s*$/, '');
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function checkWeekday(weekdayStr, parsedInput, config) {
            if (weekdayStr) {
                // TODO: Replace the vanilla JS Date object with an independent day-of-week check.
                var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
                    weekdayActual = new Date(
                        parsedInput[0],
                        parsedInput[1],
                        parsedInput[2]
                    ).getDay();
                if (weekdayProvided !== weekdayActual) {
                    getParsingFlags(config).weekdayMismatch = true;
                    config._isValid = false;
                    return false;
                }
            }
            return true;
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function calculateOffset(obsOffset, militaryOffset, numOffset) {
            if (obsOffset) {
                return obsOffsets[obsOffset];
            } else if (militaryOffset) {
                // the only allowed military tz is Z
                return 0;
            } else {
                var hm = parseInt(numOffset, 10),
                    m = hm % 100,
                    h = (hm - m) / 100;
                return h * 60 + m;
            }
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // date and time from ref 2822 format
        function configFromRFC2822(config) {
            var match = rfc2822.exec(preprocessRFC2822(config._i)),
                parsedArray;
            if (match) {
                parsedArray = extractFromRFC2822Strings(
                    match[4],
                    match[3],
                    match[2],
                    match[5],
                    match[6],
                    match[7]
                );
                if (!checkWeekday(match[1], parsedArray, config)) {
                    return;
                }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                config._a = parsedArray;
                config._tzm = calculateOffset(match[8], match[9], match[10]);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                config._d = createUTCDate.apply(null, config._a);
                config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                getParsingFlags(config).rfc2822 = true;
            } else {
                config._isValid = false;
            }
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
        function configFromString(config) {
            var matched = aspNetJsonRegex.exec(config._i);
            if (matched !== null) {
                config._d = new Date(+matched[1]);
                return;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            configFromISO(config);
            if (config._isValid === false) {
                delete config._isValid;
            } else {
                return;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            configFromRFC2822(config);
            if (config._isValid === false) {
                delete config._isValid;
            } else {
                return;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (config._strict) {
                config._isValid = false;
            } else {
                // Final attempt, use Input Fallback
                hooks.createFromInputFallback(config);
            }
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        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. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.',
            function (config) {
                config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
            }
        );
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // Pick the first defined of two or three arguments.
        function defaults(a, b, c) {
            if (a != null) {
                return a;
            }
            if (b != null) {
                return b;
            }
            return c;
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function currentDateArray(config) {
            // hooks is actually the exported moment object
            var nowValue = new Date(hooks.now());
            if (config._useUTC) {
                return [
                    nowValue.getUTCFullYear(),
                    nowValue.getUTCMonth(),
                    nowValue.getUTCDate(),
                ];
            }
            return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // convert an array to a date.
        // the array should mirror the parameters below
        // note: all values past the year are optional and will default to the lowest possible value.
        // [year, month, day , hour, minute, second, millisecond]
        function configFromArray(config) {
            var i,
                date,
                input = [],
                currentDate,
                expectedWeekday,
                yearToUse;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            currentDate = currentDateArray(config);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            //compute day of the year from weeks and weekdays
            if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
                dayOfYearFromWeekInfo(config);
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            //if the day of the year is set, figure out what it is
            if (config._dayOfYear != null) {
                yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                if (
                    config._dayOfYear > daysInYear(yearToUse) ||
                    config._dayOfYear === 0
                ) {
                    getParsingFlags(config)._overflowDayOfYear = true;
                }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                date = createUTCDate(yearToUse, 0, config._dayOfYear);
                config._a[MONTH] = date.getUTCMonth();
                config._a[DATE] = date.getUTCDate();
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // Default to current date.
            // * if no year, month, day of month are given, default to today
            // * if day of month is given, default month and year
            // * if month is given, default only year
            // * if year is given, don't default anything
            for (i = 0; i < 3 && config._a[i] == null; ++i) {
                config._a[i] = input[i] = currentDate[i];
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // Zero out whatever was not defaulted, including time
            for (; i < 7; i++) {
                config._a[i] = input[i] =
                    config._a[i] == null ? (i === 2 ? 1 : 0) : config._a[i];
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // Check for 24:00:00.000
            if (
                config._a[HOUR] === 24 &&
                config._a[MINUTE] === 0 &&
                config._a[SECOND] === 0 &&
                config._a[MILLISECOND] === 0
            ) {
                config._nextDay = true;
                config._a[HOUR] = 0;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            config._d = (config._useUTC ? createUTCDate : createDate).apply(
                null,
                input
            );
            expectedWeekday = config._useUTC
                ? config._d.getUTCDay()
                : config._d.getDay();
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // Apply timezone offset from input. The actual utcOffset can be changed
            // with parseZone.
            if (config._tzm != null) {
                config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (config._nextDay) {
                config._a[HOUR] = 24;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // check for mismatching day of week
            if (
                config._w &&
                typeof config._w.d !== 'undefined' &&
                config._w.d !== expectedWeekday
            ) {
                getParsingFlags(config).weekdayMismatch = true;
            }
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function dayOfYearFromWeekInfo(config) {
            var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            w = config._w;
            if (w.GG != null || w.W != null || w.E != null) {
                dow = 1;
                doy = 4;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                // TODO: We need to take the current isoWeekYear, but that depends on
                // how we interpret now (local, utc, fixed offset). So create
                // a now version of current config (take local/utc/offset flags, and
                // create now).
                weekYear = defaults(
                    w.GG,
                    config._a[YEAR],
                    weekOfYear(createLocal(), 1, 4).year
                );
                week = defaults(w.W, 1);
                weekday = defaults(w.E, 1);
                if (weekday < 1 || weekday > 7) {
                    weekdayOverflow = true;
                }
            } else {
                dow = config._locale._week.dow;
                doy = config._locale._week.doy;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                curWeek = weekOfYear(createLocal(), dow, doy);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                // Default to current week.
                week = defaults(w.w, curWeek.week);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                if (w.d != null) {
                    // weekday -- low day numbers are considered next week
                    weekday = w.d;
                    if (weekday < 0 || weekday > 6) {
                        weekdayOverflow = true;
                    }
                } else if (w.e != null) {
                    // local weekday -- counting starts from beginning of week
                    weekday = w.e + dow;
                    if (w.e < 0 || w.e > 6) {
                        weekdayOverflow = true;
                    }
                } else {
                    // default to beginning of week
                    weekday = dow;
                }
            }
            if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
                getParsingFlags(config)._overflowWeeks = true;
            } else if (weekdayOverflow != null) {
                getParsingFlags(config)._overflowWeekday = true;
            } else {
                temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
                config._a[YEAR] = temp.year;
                config._dayOfYear = temp.dayOfYear;
            }
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // constant that refers to the ISO standard
        hooks.ISO_8601 = function () {};
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // constant that refers to the RFC 2822 form
        hooks.RFC_2822 = function () {};
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        // date from string and format string
        function configFromStringAndFormat(config) {
            // TODO: Move this to another part of the creation flow to prevent circular deps
            if (config._f === hooks.ISO_8601) {
                configFromISO(config);
                return;
            }
            if (config._f === hooks.RFC_2822) {
                configFromRFC2822(config);
                return;
            }
            config._a = [];
            getParsingFlags(config).empty = true;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // This array is used to make a Date, either with `new Date` or `Date.UTC`
            var string = '' + config._i,
                i,
                parsedInput,
                tokens,
                token,
                skipped,
                stringLength = string.length,
                totalParsedInputLength = 0,
                era;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            tokens =
                expandFormat(config._f, config._locale).match(formattingTokens) || [];
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            for (i = 0; i < tokens.length; i++) {
                token = tokens[i];
                parsedInput = (string.match(getParseRegexForToken(token, config)) ||
                    [])[0];
                if (parsedInput) {
                    skipped = string.substr(0, string.indexOf(parsedInput));
                    if (skipped.length > 0) {
                        getParsingFlags(config).unusedInput.push(skipped);
                    }
                    string = string.slice(
                        string.indexOf(parsedInput) + parsedInput.length
                    );
                    totalParsedInputLength += parsedInput.length;
                }
                // don't parse if it's not a known token
                if (formatTokenFunctions[token]) {
                    if (parsedInput) {
                        getParsingFlags(config).empty = false;
                    } else {
                        getParsingFlags(config).unusedTokens.push(token);
                    }
                    addTimeToArrayFromToken(token, parsedInput, config);
                } else if (config._strict && !parsedInput) {
                    getParsingFlags(config).unusedTokens.push(token);
                }
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // add remaining unparsed input length to the string
            getParsingFlags(config).charsLeftOver =
                stringLength - totalParsedInputLength;
            if (string.length > 0) {
                getParsingFlags(config).unusedInput.push(string);
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // clear _12h flag if hour is <= 12
            if (
                config._a[HOUR] <= 12 &&
                getParsingFlags(config).bigHour === true &&
                config._a[HOUR] > 0
            ) {
                getParsingFlags(config).bigHour = undefined;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            getParsingFlags(config).parsedDateParts = config._a.slice(0);
            getParsingFlags(config).meridiem = config._meridiem;
            // handle meridiem
            config._a[HOUR] = meridiemFixWrap(
                config._locale,
                config._a[HOUR],
                config._meridiem
            );
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            // handle era
            era = getParsingFlags(config).era;
            if (era !== null) {
                config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            configFromArray(config);
            checkOverflow(config);
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function meridiemFixWrap(locale, hour, meridiem) {
            var isPm;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (meridiem == null) {
                // nothing to do
                return hour;
            }
            if (locale.meridiemHour != null) {
                return locale.meridiemHour(hour, meridiem);
            } else if (locale.isPM != null) {
                // Fallback
                isPm = locale.isPM(meridiem);
                if (isPm && hour < 12) {
                    hour += 12;
                }
                if (!isPm && hour === 12) {
                    hour = 0;
                }
                return hour;
            } else {
                // this is not supposed to happen
                return hour;
            }
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        // date from string and array of format strings
        function configFromStringAndArray(config) {
            var tempConfig,
                bestMoment,
                scoreToBeat,
                i,
                currentScore,
                validFormatFound,
                bestFormatIsValid = false;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (config._f.length === 0) {
                getParsingFlags(config).invalidFormat = true;
                config._d = new Date(NaN);
                return;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            for (i = 0; i < config._f.length; i++) {
                currentScore = 0;
                validFormatFound = false;
                tempConfig = copyConfig({}, config);
                if (config._useUTC != null) {
                    tempConfig._useUTC = config._useUTC;
                }
                tempConfig._f = config._f[i];
                configFromStringAndFormat(tempConfig);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                if (isValid(tempConfig)) {
                    validFormatFound = true;
                }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                // if there is any input that was not parsed add a penalty for that format
                currentScore += getParsingFlags(tempConfig).charsLeftOver;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                //or tokens
                currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                getParsingFlags(tempConfig).score = currentScore;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
                if (!bestFormatIsValid) {
                    if (
                        scoreToBeat == null ||
                        currentScore < scoreToBeat ||
                        validFormatFound
                    ) {
                        scoreToBeat = currentScore;
                        bestMoment = tempConfig;
                        if (validFormatFound) {
                            bestFormatIsValid = true;
                        }
                    }
                } else {
                    if (currentScore < scoreToBeat) {
                        scoreToBeat = currentScore;
                        bestMoment = tempConfig;
                    }
                }
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            extend(config, bestMoment || tempConfig);
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function configFromObject(config) {
            if (config._d) {
                return;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            var i = normalizeObjectUnits(config._i),
                dayOrDate = i.day === undefined ? i.date : i.day;
            config._a = map(
                [i.year, i.month, dayOrDate, i.hour, i.minute, i.second, i.millisecond],
                function (obj) {
                    return obj && parseInt(obj, 10);
                }
            );
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            configFromArray(config);
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function createFromConfig(config) {
            var res = new Moment(checkOverflow(prepareConfig(config)));
            if (res._nextDay) {
                // Adding is smart enough around DST
                res.add(1, 'd');
                res._nextDay = undefined;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function prepareConfig(config) {
            var input = config._i,
                format = config._f;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            config._locale = config._locale || getLocale(config._l);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (input === null || (format === undefined && input === '')) {
                return createInvalid({ nullInput: true });
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (typeof input === 'string') {
                config._i = input = config._locale.preparse(input);
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (isMoment(input)) {
                return new Moment(checkOverflow(input));
            } else if (isDate(input)) {
                config._d = input;
            } else if (isArray(format)) {
                configFromStringAndArray(config);
            } else if (format) {
                configFromStringAndFormat(config);
            } else {
                configFromInput(config);
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (!isValid(config)) {
                config._d = null;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function configFromInput(config) {
            var input = config._i;
            if (isUndefined(input)) {
                config._d = new Date(hooks.now());
            } else if (isDate(input)) {
                config._d = new Date(input.valueOf());
            } else if (typeof input === 'string') {
                configFromString(config);
            } else if (isArray(input)) {
                config._a = map(input.slice(0), function (obj) {
                    return parseInt(obj, 10);
                });
                configFromArray(config);
            } else if (isObject(input)) {
                configFromObject(config);
            } else if (isNumber(input)) {
                // from milliseconds
                config._d = new Date(input);
            } else {
                hooks.createFromInputFallback(config);
            }
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function createLocalOrUTC(input, format, locale, strict, isUTC) {
            var c = {};
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (format === true || format === false) {
                strict = format;
                format = undefined;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (locale === true || locale === false) {
                strict = locale;
                locale = undefined;
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            if (
                (isObject(input) && isObjectEmpty(input)) ||
                (isArray(input) && input.length === 0)
            ) {
                input = undefined;
            }
            // object construction must be done this way.
            // https://github.com/moment/moment/issues/1423
            c._isAMomentObject = true;
            c._useUTC = c._isUTC = isUTC;
            c._l = locale;
            c._i = input;
            c._f = format;
            c._strict = strict;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            return createFromConfig(c);
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        function createLocal(input, format, locale, strict) {
            return createLocalOrUTC(input, format, locale, strict, false);
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        var prototypeMin = deprecate(
                'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
                function () {
                    var other = createLocal.apply(null, arguments);
                    if (this.isValid() && other.isValid()) {
                        return other < this ? this : other;
                    } else {
                        return createInvalid();
                    }
                }
            ),
            prototypeMax = deprecate(
                'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
                function () {
                    var other = createLocal.apply(null, arguments);
                    if (this.isValid() && other.isValid()) {
                        return other > this ? this : other;
                    } else {
                        return createInvalid();
                    }
                }
            );
    
        // Pick a moment m from moments so that m[fn](other) is true for all
        // other. This relies on the function fn to be transitive.
        //
        // moments should either be an array of moment objects or an array, whose
        // first element is an array of moment objects.
        function pickBy(fn, moments) {
            var res, i;
            if (moments.length === 1 && isArray(moments[0])) {
                moments = moments[0];
            }
            if (!moments.length) {
                return createLocal();
            }
            res = moments[0];
            for (i = 1; i < moments.length; ++i) {
                if (!moments[i].isValid() || moments[i][fn](res)) {
                    res = moments[i];
                }
            }
            return res;
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        // TODO: Use [].sort instead?
        function min() {
            var args = [].slice.call(arguments, 0);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            return pickBy('isBefore', args);
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function max() {
            var args = [].slice.call(arguments, 0);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            return pickBy('isAfter', args);
    
    Romain CREY's avatar
    Romain CREY committed
        }
    
    
        var now = function () {
            return Date.now ? Date.now() : +new Date();
        };
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        var ordering = [
            'year',
            'quarter',
            'month',
            'week',
            'day',
            'hour',
            'minute',
            'second',
            'millisecond',
        ];
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function isDurationValid(m) {
            var key,
                unitHasDecimal = false,
                i;
            for (key in m) {
                if (
                    hasOwnProp(m, key) &&
                    !(
                        indexOf.call(ordering, key) !== -1 &&
                        (m[key] == null || !isNaN(m[key]))
                    )
                ) {
                    return false;
                }
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
            for (i = 0; i < ordering.length; ++i) {
                if (m[ordering[i]]) {
                    if (unitHasDecimal) {
                        return false; // only allow non-integers for smallest unit
                    }
                    if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
                        unitHasDecimal = true;
                    }
                }
            }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function isValid$1() {
            return this._isValid;
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function createInvalid$1() {
            return createDuration(NaN);
        }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
        function Duration(duration) {
            var normalizedInput = normalizeObjectUnits(duration),