检查字符串是否为日期值

Thy*_*hys 183 javascript date-format

检查值是否为有效日期,允许使用任何已知日期格式的简单方法是什么.

比如我有值10-11-2009,10/11/2009,2009-11-10T07:00:00+0000它都应该被视为日期值,和值200,10,350,不应被视为一个日期值.如果可能的话,最简单的检查方法是什么?因为时间戳也是允许的.

rsp*_*rsp 221

2015年更新

这是一个老问题,但其他新问题如下:

关闭这个重复,所以我认为在这里添加一些新信息很重要.我正在写它是因为我害怕以为人们实际上复制并粘贴了这里发布的一些代码并在生产中使用它.

这里的大多数答案使用了一些复杂的正则表达式,这些表达式只匹配一些非常特定的格式,并且实际上做得不正确(比如匹配1月32日,而不像广告中那样匹配实际的ISO日期 - 请参阅演示)或者他们尝试将任何内容传递给Date构造函数和希望最好的.

使用时刻

正如我在这个答案中解释的那样,目前有一个可用的库: Moment.js

它是一个用JavaScript解析,验证,操作和显示日期的库,它具有比标准JavaScript日期处理函数更丰富的API.

它是12kB缩小/ gzip并在Node.js和其他地方工作:

bower install moment --save # bower
npm install moment --save   # npm
Install-Package Moment.js   # NuGet
spm install moment --save   # spm
meteor add momentjs:moment  # meteor
Run Code Online (Sandbox Code Playgroud)

使用Moment,您可以非常具体地检查有效日期.有时候添加一些关于你期望的格式的线索是非常重要的.例如,2015年6月22日之类的日期看起来像一个有效的日期,除非您使用格式DD/MM/YYYY,在这种情况下,该日期应被视为无效.您可以通过几种方式告诉Moment您期望的格式,例如:

moment("06/22/2015", "MM/DD/YYYY", true).isValid(); // true
moment("06/22/2015", "DD/MM/YYYY", true).isValid(); // false
Run Code Online (Sandbox Code Playgroud)

true参数是有那么瞬间将不尝试解析输入,如果它不正好符合所提供的格式之一(它应该是在我看来,一个默认的行为).

您可以使用内部提供的格式:

moment("2015-06-22T13:17:21+0000", moment.ISO_8601, true).isValid(); // true
Run Code Online (Sandbox Code Playgroud)

您可以使用多种格式作为数组:

var formats = [
    moment.ISO_8601,
    "MM/DD/YYYY  :)  HH*mm*ss"
];
moment("2015-06-22T13:17:21+0000", formats, true).isValid(); // true
moment("06/22/2015  :)  13*17*21", formats, true).isValid(); // true
moment("06/22/2015  :(  13*17*21", formats, true).isValid(); // false
Run Code Online (Sandbox Code Playgroud)

见:DEMO.

其他图书馆

如果您不想使用Moment.js,还有其他库:

2016年更新

我创建的immoment模块就像是Moment的一部分,但没有因现有对象的变异而引起的惊喜(有关更多信息,请参阅文档).

2018年更新

今天我建议使用Luxon进行日期/时间操作而不是Moment,它(不像Moment)使所有对象都不可变,因此没有与日期的隐式变异相关的令人讨厌的惊喜.

更多信息

也可以看看:

Rob Gravelle关于JavaScript解析库的一系列文章:

底线

当然,任何人都可以尝试重新发明轮子,写一个正则表达式(但是在你做之前实际读取ISO 8601和RFC 3339)或者用随机数据调用buit-in构造函数来解析错误消息,如'Invalid Date'(你确定这个消息是在所有平台上完全相同?在所有语言环境中?未来?)或者您可以使用经过测试的解决方案并利用您的时间来改进它,而不是重新发明它.这里列出的所有库都是开源的免费软件.

  • @krivar最好像这样使用它:`moment("06/22/2015","DD/MM/YYYY",true).isValid();`显式提供了预期的日期格式,参数为`true `意思是严格检查.我用更多信息和更好的例子更新了我的答案. (4认同)
  • 这可能是我在SO上看到的最好和最完善的答案 (3认同)
  • 究竟应该如何使用它?`moment("无论123").isValid()`返回`true`. (2认同)
  • 虽然如此,但我正在验证用户输入,我不知道预期的日期格式...... (2认同)
  • @JanVanderHaegen 如果您不知道预期的日期格式,那么如何验证任何内容?猜测的问题是,当你有 03/22/99 时,你可以猜测它并且你认为它是有效的。如果您的日期是 22/03/99,那么日期也很明显。但是你会遇到 03/04/99 或更糟的 03/04/05 问题,因为至少有 3 种不同的方式可以解释它,如果你不知道预期的格式,那么如果你如果您不知道它的含义,请说它是有效的。因此,我总是建议使用显式格式,最好是 ISO 字符串。 (2认同)
  • @JanVanderHaegen如果可以假设3/4/5是有效日期,那么2015年4月1日那么我会建议将这些格式(可能还有更多)添加到支持格式的明确列表中.请注意,如果没有明确的格式,您提到的3/4/5是不明确的. (2认同)

Nei*_*rdi 61

这就是我现在正在处理的应用程序中解决这个问题的方法:

根据krillgar的反馈更新:

var isDate = function(date) {
    return (new Date(date) !== "Invalid Date") && !isNaN(new Date(date));
}
Run Code Online (Sandbox Code Playgroud)

要么...

var isDate = function(date) {
    return (new Date(date) !== "Invalid Date" && !isNaN(new Date(date)) ) ? true : false;
}
Run Code Online (Sandbox Code Playgroud)

....

  • 这不是一个好的答案.`new Date(date)!=="Invalid Date"`将**总是**返回*true*因为左表达式将返回一个Date对象,其时间值为*NaN*,它永远不会是`===`到一个字符串.由于类型转换,使用`==`"工作".但是由于日期字符串的解析仍然主要依赖于实现,依靠它来解析随机格式我们严重缺陷. (10认同)
  • 我需要为节点返回(new Date(date)).toString()!=="Invalid Date".还要注意吗?true:false是多余的.只需返回表达式就足够了. (5认同)
  • 新日期("469")结果于Tue Jan 01 469 00:00:00 GMT + 0200(EET) (3认同)
  • 这类似于被错误接受的正确答案。isDate('Mac OS X 10.14.2')在这里返回true。 (2认同)

Asm*_*mor 42

Date.parse()足够了?

请参阅其相关的MDN文档页面.

  • 小心的另一个原因 - 数字解析为日期.`Date.parse("4.3")`是`986270400000`. (52认同)
  • 对不起@Asmor,这不是一个正确的答案.Date.parse将解析任何带有数字的字符串. (48认同)
  • 请注意这一点,因为它仍然会返回2月份无效日期的返回值,例如:2013-02-31 (21认同)
  • Date.parse(“我的名字8”)作为99662040000来了,这是错误的。我用了这个,现在痛苦了。 (6认同)
  • 我对上面的两个“警告”案例都做了一个尝试:console.log(Date.parse("2013-02-31")); console.log(Date.parse("4.3")); 并且在这两种情况下(在 Firefox 上)它都返回 NaN,所以对我来说,Date.parse 似乎没问题(无论如何,我在解析之前预先验证了破折号和正确的长度)。 (2认同)

kri*_*gar 22

new Date(date) === 'Invalid Date'仅适用于Firefox和Chrome.IE8(我在我的机器上用于测试目的)给出了NaN.

正如已接受的答案所述,Date.parse(date)也适用于数字.因此,为了解决这个问题,你还可以检查它不是一个数字(如果这是你要确认的东西).

var parsedDate = Date.parse(date);

// You want to check again for !isNaN(parsedDate) here because Dates can be converted
// to numbers, but a failed Date parse will not.
if (isNaN(date) && !isNaN(parsedDate)) {
    /* do your work */
}
Run Code Online (Sandbox Code Playgroud)

  • 不起作用。如果“date”是“Foostreet 1”,则您的条件被评估为 true。 (3认同)
  • 我意识到这是几年后的事了,但 `isNan` 不是一个函数;一审不正确。 (2认同)

lpr*_*hap 10

使用正则表达式来验证它。

isDate('2018-08-01T18:30:00.000Z');

isDate(_date){
        const _regExp  = new RegExp('^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$');
        return _regExp.test(_date);
    }
Run Code Online (Sandbox Code Playgroud)

  • 这不会测试非真实日期(例如 2/31/2021)的字符串。 (2认同)

Yuv*_*til 10

function isDate(dateStr) {
  return !isNaN(new Date(dateStr).getDate());
}
Run Code Online (Sandbox Code Playgroud)
  • 这将适用于任何浏览器,因为它不依赖于“无效日期”检查。
  • 这将适用于 ES6 之前的遗留代码。
  • 这将在没有任何库的情况下工作。
  • 无论日期格式如何,这都将起作用。
  • 这不依赖于 Date.parse 当像“蜘蛛侠 22”这样的值在日期字符串中时,它会失败。
  • 这并不要求我们编写任何 RegEx。

  • 注意,isDate('4.3') 和 isDate('xxx 8') 都返回 true (6认同)
  • 不幸的是,关于不依赖“Date.parse”的声明是不正确的,因为上述构造函数和使用字符串函数调用的“Date()”构造函数几乎完全相同。 (3认同)
  • 你好!虽然此代码可以解决问题,但[包括解释](https://meta.stackexchange.com/q/114762) 如何以及为何解决问题将真正有助于提高帖子的质量,并且可能会产生结果更多的赞成票。请记住,您是在为将来的读者回答问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 (2认同)

jwe*_*rre 7

这样的事怎么样?它将测试它是Date对象还是日期字符串:

function isDate(value) {
    var dateFormat;
    if (toString.call(value) === '[object Date]') {
        return true;
    }
    if (typeof value.replace === 'function') {
        value.replace(/^\s+|\s+$/gm, '');
    }
    dateFormat = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/;
    return dateFormat.test(value);
}
Run Code Online (Sandbox Code Playgroud)

我应该提一下,这不会测试ISO格式化的字符串,但是对RegExp做更多的工作你应该是好的.


yka*_*ica 7

此处没有答案可以检查日期是否无效,例如2月31日。此功能通过检查返回的月份是否等于原始月份并确保提供了有效的年份来解决该问题。

//expected input dd/mm/yyyy or dd.mm.yyyy or dd-mm-yyyy
function isValidDate(s) {
  var separators = ['\\.', '\\-', '\\/'];
  var bits = s.split(new RegExp(separators.join('|'), 'g'));
  var d = new Date(bits[2], bits[1] - 1, bits[0]);
  return d.getFullYear() == bits[2] && d.getMonth() + 1 == bits[1];
} 
Run Code Online (Sandbox Code Playgroud)


小智 7

通过参考以上所有评论,我得出了一个解决方案。

如果Date传递的是 ISO 格式或需要处理其他格式,则此方法有效。

var isISO = "2018-08-01T18:30:00.000Z";

if (new Date(isISO) !== "Invalid Date" && !isNaN(new Date(isISO))) {
    if(isISO == new Date(isISO).toISOString()) {
        console.log("Valid date");
    } else {
        console.log("Invalid date");
    }
} else {
    console.log("Invalid date");
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里玩JSFiddle。

  • 对于javascript,这是有效的,但是如何在打字稿中使用它? (2认同)

小智 5

我知道这是一个老问题,但我遇到了同样的问题,发现没有一个答案能正常工作——特别是从日期中剔除数字(1,200,345 等),这是最初的问题。这是我能想到的一个相当非正统的方法,它似乎有效。是否有失败的情况请指出。

if(sDate.toString() == parseInt(sDate).toString()) return false;
Run Code Online (Sandbox Code Playgroud)

这是删除数字的行。因此,整个函数可能如下所示:

if(sDate.toString() == parseInt(sDate).toString()) return false;
Run Code Online (Sandbox Code Playgroud)

  • `console.log("hello 1 ", isDate("hello 1 "));` 返回 true (2认同)

A-S*_*ani 5

这是一个仅使用的改进函数Date.parse()

function isDate(s) {
    if(isNaN(s) && !isNaN(Date.parse(s)))
        return true;
    else return false;
}
Run Code Online (Sandbox Code Playgroud)

注意: Date.parse() 将解析数字:例如Date.parse(1)将返回一个日期。所以在这里我们检查是否s不是数字,如果是日期。

  • 这不起作用,因为通过“测试 2”将作为真实日期通过。在最新版本的 chrome 中进行了测试 (2认同)