Node.js - 检查字符串是否代表大量元素的有效日期时间的最快方法是什么?

sme*_*its 4 javascript performance node.js

检查有效DateTime的最快方法是什么? 我不仅需要考虑字符串中的年份,月份,日期,小时和分钟,还要考虑日期时间是否有效,例如:2017-02-29 10:00应被视为无效,因为它是第29位一个非闰年.

我有一个字符串元素数组(300k元素)格式:YYYYMMDDHHmm,我需要以最快的方式检查每一行.

使用moment.js来检查每个元素的有效性需要5s在常规的for循环中:

for (let i = 0; i < length; i++) {
    let el = datetimes[i];
    let d = moment.utc(el, "YYYYMMDDHHmm");
    d.isValid();
}
Run Code Online (Sandbox Code Playgroud)

有更快的替代品吗?

Ste*_*gin 6

在调用任何类型的字符串匹配器或正则表达式之前,尽可能多地排除规则.

每时每刻都会评估这个表达.(除非是创意缓存正在进行)

您可以先检查falsy值(undefined,null,0,''等).

if (!el) {
    // not valid
}
Run Code Online (Sandbox Code Playgroud)

检查null和undefined后你可以查看长度(感谢Luca)

if (el.length !== 12) {
   // not valid
}
Run Code Online (Sandbox Code Playgroud)

您还可以预编译REGEX并使用它.

// define this outside of your loop
let rx2 = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})$/

function leapYear(year) {
  return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}

function checkValidDate(strDate) {
  if (!strDate || strDate.length !== 12) throw new Error('invalid date')
  let m = rx2.exec(strDate)
  if (!m) throw new Error('invalid date')

  let year = parseInt(m[1])
  if (year < 2000 || year >= 2100) throw new Error('bad year')

  let month = parseInt(m[2])
  if (month > 11) throw new Error('bad month')

  let day = parseInt(m[3])
  // base 0 days and months
  switch (month) {
    case 0, 2, 4, 5, 6, 7, 9, 11:
      if (day > 30) throw new Error('bad day')
      break;
    case 3, 5, 8, 10:
      if (day > 29) throw new Error('bad day')
      break;
    case 1:
      if (day > 28) throw new Error('bad day')
      if (day === 28 && !isLeapYear(year)) throw new Error('bad day')
      break;
  }

  let hour = parseInt(m[4])
  if (hour > 23) throw new Error('bad hour')

  let minute = parseInt([5])
  if (hour > 59) throw new Error('bad minute')
}

try {
  checkValidDate('asdf')
  console.log('valid')
} catch (e) {
  console.error(e)
}

try {
  checkValidDate('200011241230')
  console.log('valid')
} catch (e) {
  console.error(e)
}

try {
  checkValidDate('200001300000')
  console.log('valid')
} catch (e) {
  console.error(e)
}
Run Code Online (Sandbox Code Playgroud)