Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a string is a date or not

I have the following strings:

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

I want to check, whether the string is a date or not.

I tried:

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

, but it returns true for a='Check 123', whenever it has numbers.

What could be a better solution?

Note: I do not want to use momentjs, because of project restrictions

like image 475
Marium Malik Avatar asked Sep 16 '25 14:09

Marium Malik


2 Answers

It is possible to check whether the string contains year, month, day. In addition, we can add some conditions to have stricter rules to define whether string is Date:

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

An example:

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'))
like image 139
StepUp Avatar answered Sep 18 '25 05:09

StepUp


Actually, the question should be: how to determine if a given string can be converted to a real Date object?

Now, more things than you like may be converted to a Date (e.g., try new Date("") or new Date(0)). So you may want to use your own restrictions as to what you want to convert. Here's a method that restricts input to either a real Date object or a 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; }

The previous snippet will not always give you the desired result (see comments).

Alternatively you can also write a parser of some kind to determine if the given string can be converted to Date, to be more (but not 100%) certain that a string is convertable to Date. Something like:

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; }
like image 35
KooiInc Avatar answered Sep 18 '25 04:09

KooiInc