На самом деле, вопрос должен быть: как определить, может ли данная строка быть преобразована в реальный Date
объект ?
Теперь можно конвертировать больше вещей, чем вам нравится до Date
(например, попробуйте new Date("")
или new Date(0)
). Поэтому вы можете использовать свои собственные ограничения в отношении того, что вы хотите конвертировать. Вот метод, который ограничивает ввод либо реальным Date
объектом, либо String
:
const canConvertToDate = trial =>
[String, Date].includes(trial.constructor) &&
!isNaN(new Date(trial));
console.log(`canConvertToDate(\`\`): ${canConvertToDate(``)}`);
console.log(`canConvertToDate(\`no dice\`): ${canConvertToDate(`no dice`)}`);
console.log(`canConvertToDate(new Date): ${canConvertToDate(new Date)}`);
console.log(`canConvertToDate(\`2020-03-03 00:00:00\`): ${
canConvertToDate(`2020-03-03 00:00:00`)}`);
console.log(`canConvertToDate(0): ${canConvertToDate(0)}`);
console.log(`canConvertToDate(\`Wed, 11 Mar 2020 09:27:50 GMT\`): ${
canConvertToDate(`Wed, 11 Mar 2020 09:27:50 GMT`)}`);
console.log(`canConvertToDate(new Date().toUTCString()): ${
canConvertToDate(new Date().toUTCString())}`);
console.log(`canConvertToDate(134): ${canConvertToDate(134)}`);
// Please note the browser difference (Chrome / Firefox)
console.log(`canConvertToDate(\`134\`): ${canConvertToDate(`134`)}`);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Предыдущий фрагмент не всегда даст желаемый результат (см. Комментарии).
В качестве альтернативы вы также можете написать какой-нибудь синтаксический анализатор, чтобы определить, можно ли преобразовать данную строку в Date
, чтобы быть более (но не на 100%) уверенным, что строка может быть преобразована в Date
. Что-то вроде:
console.log(`tryParseDate(\`\`): ${tryParseDate(``).date}`);
console.log(`tryParseDate(new Date): ${tryParseDate(new Date).date}`);
console.log(`tryParseDate(\`Wed, 11 Mar 2020 09:27:50 GMT\`): ${
tryParseDate(`Wed, 11 Mar 2020 09:27:50 GMT`).date}`);
console.log(`tryParseDate(\`check 134\`): ${tryParseDate(`check 134`).date}`);
console.log(`tryParseDate(\`3-3-2005\`, \`ddmmyyyy\`): ${
tryParseDate(`03-03-2005`, `ddmmyyyy`).date}`);
console.log(`tryParseDate(\`12-22-1998 22:22:10.345\`, \`mmddyyyy\`): ${
tryParseDate(`12-22-1998 22:22:10.345`, `mmddyyyy`).date}`);
console.log(`tryParseDate(\`29-02-2019 22:22:10.345\`, \`ddmmyyyy\`): ${
tryParseDate(`29-02-2019 22:22:10.345`, `ddmmyyyy`).date}`);
function tryParseDate(someString, format = `yyyymmdd`) {
const invalid = {cando: false, date: new Date(`invalid`)};
if (someString.constructor !== String) { return { ...invalid, date: `Invalid Date: input not a string` }; }
const between = (val, lower, upper) => val >= lower && val <= upper;
const d = someString.split(/[/\- T:.]/g);
if (d.length < 3) { return {...invalid, date: `Invalid Date: can't split to anything useful`}; }
const formats = format.match(/(yyyy)|(mm)|(dd)/gi);
const values = {
year: +d[formats.findIndex(v => v === `yyyy`)],
month: +d[formats.findIndex(v => v === `mm`)],
date: +d[formats.findIndex(v => v === `dd`)] };
const cando = !isNaN(values.year) && values.year > 0 &&
!isNaN(values.month) && between(values.month, 1, 12)
!isNaN(values.date) && between(values.date, 1, 31);
if (!cando) {
return {...invalid, date: `Invalid Date: the given value is not valid`};
}
const date2Parse = `${d[formats.findIndex(v => v=== `yyyy`)]}/${
d[formats.findIndex(v => v=== `mm`)]}/${
d[formats.findIndex(v => v=== `dd`)]} ${
d.slice(3).map((v, i) => !i ? v : i > 2 ? `.${v}` : `:${v}`).join(``)}`;
const parsed = new Date(date2Parse);
const checkLeap = parsed.getMonth() + 1 === values.month;
const error = `Impossible Date: ${
!checkLeap ? `${values.year} not a leap year` : `parsing failed`}`;
return isNaN(parsed) || !checkLeap
? {...invalid, date: error}
: {cando: true, date: parsed};
}
.as-console-wrapper { top: 0; max-height: 100% !important; }