Проверьте, является ли строка датой или нет - PullRequest
2 голосов
/ 11 марта 2020

У меня есть следующие строки:

a='Check 134', a='2020-01-15T10:47:54Z', a='1234', a= some object

Я хочу проверить, является ли строка датой или нет.

Я пробовал:

new Date(a) instanceof Date &&
        !isNaN(new Date(a).getTime())

, но он возвращает true для a = 'Check 123' всякий раз, когда у него есть числа.

Что может быть лучшим решением?

Примечание: я не хочу использовать момент js из-за ограничений проекта

Ответы [ 7 ]

2 голосов
/ 11 марта 2020

На самом деле, вопрос должен быть: как определить, может ли данная строка быть преобразована в реальный 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; }
1 голос
/ 11 марта 2020

Поскольку вы уже знаете формат дат, которые вы хотите проверить, используйте момент js и проверьте формат

var moment = require("moment");
var res = moment("Check 123", "YYYY-MM-DD", true).isValid();
console.log(res);
0 голосов
/ 11 марта 2020

Просто используйте оператор typeof. Нет необходимости использовать какие-либо внешние библиотеки.

if (typeof date === 'object') {
    // date is object
}
if (typeof date === 'string') {
//date is string
} 
0 голосов
/ 11 марта 2020

Можно проверить, содержит ли строка year, month, day. Кроме того, мы можем добавить некоторые условия, чтобы более строгие правила определяли, является ли строка Date:

const isDate = str => {
    let [y,M,d,h,m,s] = str.split(/[- : T Z]/);
    return (y && M <= 12 && d <= 31) ? true : false;
} 

Пример:

const isDate = str => {
    let [y,M,d,h,m,s] = str.split(/[- : T Z]/);
    return (y && M <= 12 && d <= 31) ? true : false;
}

console.log('Check 134', isDate('Check 134'))
console.log('2020-01-15T10:47:54Z', isDate('2020-01-15T10:47:54Z'))
console.log('1234', isDate('1234'))
console.log('13-13-13', isDate('13-13-13'))
0 голосов
/ 11 марта 2020

Вот простая функция, которая использует Date.parse () внутренне; когда вы передаете строку с пробелами в Date.parse(), она игнорирует не-di git символы и возвращает положительное значение; следовательно, вам нужно удалить пробелы перед тем, как передать его Date.parse()

const a= 'Check 134';
const b= '2020-01-15T10:47:54Z';
const c= '1234';
const tricky = '1'; // a number from -12 to 13 is valid

function isValidDate (str) {
  // optional condition to eliminate the tricky ones
  // since chrome will prepend zeros (000...) to the string and then parse it
  let noSpace = str.replace(/\s/g, '')
  if( noSpace.length < 3) {
    return false
  }
  return Date.parse(noSpace) > 0
}

console.log(a,isValidDate(a))
console.log(b,isValidDate(b))
console.log(c,isValidDate(c))
console.log(tricky,isValidDate(tricky))

// only in chrome
console.log("'1' is ", Date.parse('1') > 1 ," since it can be ", new Date('1').toString())

Редактировать: еще есть несколько предостережений для работы Дата в Chrome, поскольку у нее есть открытый вопрос по этому вопросу, вокруг нее много дискуссий, проверьте это ТАК вопрос сложные угловые случаи в chrome - это нечто большее; Кажется, лучший способ запустить его Chrome - узнать ожидаемый тип ввода и проверить его в соответствии с ним; (например, формат даты RF C 2822 / ISO 8601). Существуют надежные регулярные выражения для известных форматов дат, которые можно использовать и подтверждать, но попытки проверить все доступные форматы дат в chrome на данный момент имеют множество угловых случаев и потенциальных ложных срабатываний

0 голосов
/ 11 марта 2020

Вы можете попробовать использовать Date.parse () , а затем проверить положительное число (дата> 0). Например:

Date.parse('2020-01-15T10:47:54Z') // 1579085274000
Date.parse('123') // -23225875200000
Date.parse('Check 134') // -57938551324000

https://jsfiddle.net/zmLbh0tu/

0 голосов
/ 11 марта 2020

Вы можете использовать Date.parse(). Если он возвращает положительное значение, то он действителен, иначе нет. Например: -

Date.parse("2020-01-15T10:47:54Z")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...