calendar: defaultCalendar,
longDateFormat: defaultLongDateFormat,
invalidDate: defaultInvalidDate,
dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
relativeTime: defaultRelativeTime,
months: defaultLocaleMonths,
monthsShort: defaultLocaleMonthsShort,
weekdays: defaultLocaleWeekdays,
weekdaysMin: defaultLocaleWeekdaysMin,
weekdaysShort: defaultLocaleWeekdaysShort,
meridiemParse: defaultLocaleMeridiemParse,
// internal storage for locale config files
function commonPrefix(arr1, arr2) {
minl = Math.min(arr1.length, arr2.length);
for (i = 0; i < minl; i += 1) {
if (arr1[i] !== arr2[i]) {
function normalizeLocale(key) {
return key ? key.toLowerCase().replace('_', '-') : key;
// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function chooseLocale(names) {
while (i < names.length) {
split = normalizeLocale(names[i]).split('-');
next = normalizeLocale(names[i + 1]);
next = next ? next.split('-') : null;
locale = loadLocale(split.slice(0, j).join('-'));
commonPrefix(split, next) >= j - 1
//the next array item is better than a shallower substring of this one
function loadLocale(name) {
// TODO: Find a better way to register and load all the locales in Node
locales[name] === undefined &&
typeof module !== 'undefined' &&
oldLocale = globalLocale._abbr;
aliasedRequire = require;
aliasedRequire('./locale/' + name);
getSetGlobalLocale(oldLocale);
// mark as not found to avoid repeating expensive file require call causing high CPU
// when trying to find en-US, en_US, en-us for every format call
locales[name] = null; // null means not found
// This function will load locale and then set the global locale. If
// no arguments are passed in, it will simply return the current global
function getSetGlobalLocale(key, values) {
if (isUndefined(values)) {
data = defineLocale(key, values);
// moment.duration._locale = moment._locale = data;
if (typeof console !== 'undefined' && console.warn) {
//warn user if arguments are passed but the locale could not be set
'Locale ' + key + ' not found. Did you forget to load it?'
return globalLocale._abbr;
function defineLocale(name, config) {
parentConfig = baseConfig;
if (locales[name] != null) {
'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;
locale = loadLocale(config.parentLocale);
parentConfig = locale._config;
if (!localeFamilies[config.parentLocale]) {
localeFamilies[config.parentLocale] = [];
localeFamilies[config.parentLocale].push({
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);
function updateLocale(name, config) {
parentConfig = baseConfig;
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));
tmpLocale = loadLocale(name);
parentConfig = tmpLocale._config;
config = mergeConfigs(parentConfig, config);
// updateLocale is called for creating a new locale
// Set abbr so it will have a name (getters return
locale = new Locale(config);
locale.parentLocale = locales[name];
// backwards compat for now: also set the locale
getSetGlobalLocale(name);
// 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) {
function getLocale(key) {
if (key && key._locale && key._locale._abbr) {
//short-circuit everything else
locale = loadLocale(key);
return chooseLocale(key);
function checkOverflow(m) {
if (a && getParsingFlags(m).overflow === -2) {
a[MONTH] < 0 || a[MONTH] > 11
: a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH])
: a[MINUTE] < 0 || a[MINUTE] > 59
: a[SECOND] < 0 || a[SECOND] > 59
: a[MILLISECOND] < 0 || a[MILLISECOND] > 999
getParsingFlags(m)._overflowDayOfYear &&
(overflow < YEAR || overflow > DATE)
if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
getParsingFlags(m).overflow = overflow;
// 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)?/,
['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}/],
['GGGG[W]WWE', /\d{4}W\d{3}/],
['GGGG[W]WW', /\d{4}W\d{2}/, false],
['YYYYMM', /\d{6}/, false],
['YYYY', /\d{4}/, false],
// iso time formats and regexes
['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/],
['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/],
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}))$/,
function configFromISO(config) {
match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
getParsingFlags(config).iso = true;
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;
if (dateFormat == null) {
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];
if (timeFormat == null) {
if (!allowTime && timeFormat != null) {
if (tzRegex.exec(match[4])) {
config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
configFromStringAndFormat(config);
function extractFromRFC2822Strings(
defaultLocaleMonthsShort.indexOf(monthStr),
result.push(parseInt(secondStr, 10));
function untruncateYear(yearStr) {
var year = parseInt(yearStr, 10);
} else if (year <= 999) {
function preprocessRFC2822(s) {
// Remove comments and folding whitespace and replace multiple-spaces with a single space
.replace(/\([^)]*\)|[\n\t]/g, ' ')
.replace(/(\s\s+)/g, ' ')
function checkWeekday(weekdayStr, parsedInput, config) {
// TODO: Replace the vanilla JS Date object with an independent day-of-week check.
var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
weekdayActual = new Date(
if (weekdayProvided !== weekdayActual) {
getParsingFlags(config).weekdayMismatch = true;
function calculateOffset(obsOffset, militaryOffset, numOffset) {
return obsOffsets[obsOffset];
} else if (militaryOffset) {
// the only allowed military tz is Z
var hm = parseInt(numOffset, 10),
// date and time from ref 2822 format
function configFromRFC2822(config) {
var match = rfc2822.exec(preprocessRFC2822(config._i)),
parsedArray = extractFromRFC2822Strings(
if (!checkWeekday(match[1], parsedArray, config)) {
config._tzm = calculateOffset(match[8], match[9], match[10]);