【问题标题】:Check if a string is a date or not检查字符串是否为日期
【发布时间】:2020-06-23 05:11:37
【问题描述】:

我有以下字符串:

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

我想检查字符串是否为日期。

我试过了:

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

,但对于 a='Check 123',只要它有数字,它就会返回 true。

还有什么更好的解决方案?

注意:由于项目限制,我不想使用momentjs

【问题讨论】:

  • “1234”是否被视为有效日期...?它可以被解释为 UNIX 时间戳,但可能不是。您对您认为有效的日期有更好的定义吗?也许您想使用正则表达式强制执行特定格式?
  • 我的日期是这样的:2020-01-15T10:47:54Z
  • @Smough 我找不到日期类型的任何内容。它用于字符串、数字等,我的日期被视为字符串
  • /\d+-\d+-\d+T\d+:\d+:\d+Z/.match(a)...?

标签: javascript angular typescript


【解决方案1】:

您可以使用Date.parse()。如果它返回正值,那么它是有效的,否则不是。例如:-

Date.parse("2020-01-15T10:47:54Z")

【讨论】:

  • 它返回 true 为 Date.parse('Check 134') 我也试过了
【解决方案2】:

您可以尝试使用Date.parse(),然后检查一个正数(日期> 0)。 例如:

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

https://jsfiddle.net/zmLbh0tu/

【讨论】:

  • Check 134 对我来说是真的
【解决方案3】:

由于您已经知道要检查的日期的格式,因此可以使用 momentjs 并检查格式

var moment = require("moment");
var res = moment("Check 123", "YYYY-MM-DD", true).isValid();
console.log(res);

【讨论】:

  • @MoannaTabala 当然它会返回 false,因为模式不匹配。这种方法最有效,当你知道格式时,它被作为函数中的第二个参数
【解决方案4】:

这是一个内部使用Date.parse()的简单函数;当您将带有空格的字符串传递给Date.parse() 时,它将忽略非数字字符并返回正数;因此您需要在将空格字符传递给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 中使用 Date 仍有一些注意事项,因为它对此有未解决的问题,围绕它有很多讨论,请查看SO question chrome 中棘手的角落案例不止于此;运行 Chrome 的最佳方法似乎是了解您预期的输入类型并根据它进行验证; (例如 RFC 2822/ISO 8601 日期格式)。有用于已知日期格式的强大正则表达式可以使用和确认,但目前尝试在 chrome 中验证所有可用的日期格式有很多极端情况和潜在的误报

【讨论】:

  • Date.parse('1') 返回978307200000
  • @phuzi 1 是 chrome v8 中的有效日期;它甚至会在new Date('1').toString() 中解析并返回结果:)。如果你在 firefox(spiderMoneky) 引擎中运行它,它不会说 1 是一个有效的日期。
  • 它不符合 OPs 的要求。日期似乎是 ISO8601 格式。
  • @phuzi 实际上,没关系; Date.parse('1') == Date.parse('001') 因为它可以是“2001 年 1 月 1 日”
  • @CaptainMhmdrz_A 有可能将 1 作为我的变量值,它会在那种情况下中断吗?
【解决方案5】:

可以检查字符串是否包含yearmonthday。另外,我们可以添加一些条件来有更严格的规则来定义字符串是否为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'))

【讨论】:

  • 会有边缘情况。例如,尝试isDate(new Date().toUTCString())
  • @KooiInc 是的,你是对的,但我不知道 OP 是否想检查这种极端情况
【解决方案6】:

只需使用 typeof 运算符。无需使用任何外部库。

if (typeof date === 'object') {
    // date is object
}
if (typeof date === 'string') {
//date is string
} 

【讨论】:

    【解决方案7】:

    其实问题应该是:如何判断给定的字符串是否可以转换为真正的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; }

    之前的 sn-p 不会总是给你想要的结果(见 cmets)。

    或者,您也可以编写某种解析器来确定给定字符串是否可以转换为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; }

    【讨论】:

    • 会有边缘情况,例如Check 134
    • @StepUp:检查(见答案)。边缘是什么?
    • 我尝试使用console.log(Check 134: ${ canConvertToDate('Check 134')});,它返回true
    • 是的,这是在 Chrome 中,我想这是一个我们应该提交的错误。 Chrome 提供的此类字符串中的日期:Fri Jan 01 0134 00:00:00 GMT+0019 (Central European Standard Time)。火狐给Invalid Date
    • 完成。尽管如此,从字符串或几个数字转换是出了名的困难而不简单。所以像isDate 这样的东西应该只是恕我直言的第一道防线。之后,明智的做法是检查转换后的 Date 是否符合您对它的合理期望。
    猜你喜欢
    • 2011-11-18
    • 1970-01-01
    • 2018-06-15
    • 1970-01-01
    • 2012-06-17
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多