import { configFromStringAndFormat } from './from-string-and-format';
|
import { createUTCDate } from './date-from-array';
|
import { hooks } from '../utils/hooks';
|
import { deprecate } from '../utils/deprecate';
|
import getParsingFlags from './parsing-flags';
|
import { defaultLocaleMonthsShort } from '../units/month';
|
import { defaultLocaleWeekdaysShort } from '../units/day-of-week';
|
|
// 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,
|
};
|
|
// date from iso format
|
export function configFromISO(config) {
|
var i,
|
l,
|
string = config._i,
|
match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
|
allowTime,
|
dateFormat,
|
timeFormat,
|
tzFormat;
|
|
if (match) {
|
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;
|
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),
|
];
|
|
if (secondStr) {
|
result.push(parseInt(secondStr, 10));
|
}
|
|
return result;
|
}
|
|
function untruncateYear(yearStr) {
|
var year = parseInt(yearStr, 10);
|
if (year <= 49) {
|
return 2000 + year;
|
} else if (year <= 999) {
|
return 1900 + year;
|
}
|
return year;
|
}
|
|
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*$/, '');
|
}
|
|
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;
|
}
|
|
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;
|
}
|
}
|
|
// date and time from ref 2822 format
|
export 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;
|
}
|
|
config._a = parsedArray;
|
config._tzm = calculateOffset(match[8], match[9], match[10]);
|
|
config._d = createUTCDate.apply(null, config._a);
|
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
|
|
getParsingFlags(config).rfc2822 = true;
|
} else {
|
config._isValid = false;
|
}
|
}
|
|
// date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
|
export function configFromString(config) {
|
var matched = aspNetJsonRegex.exec(config._i);
|
if (matched !== null) {
|
config._d = new Date(+matched[1]);
|
return;
|
}
|
|
configFromISO(config);
|
if (config._isValid === false) {
|
delete config._isValid;
|
} else {
|
return;
|
}
|
|
configFromRFC2822(config);
|
if (config._isValid === false) {
|
delete config._isValid;
|
} else {
|
return;
|
}
|
|
if (config._strict) {
|
config._isValid = false;
|
} else {
|
// 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. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.',
|
function (config) {
|
config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
|
}
|
);
|