检查字符串是否为日期值

有什么简单的方法来检查一个值是否为有效日期,允许任何已知的日期格式。

例如,我的值10-11-200910/11/20092009-11-10T07:00:00+0000都应该被识别为日期值,而值20010350不应该被识别为日期值。如果可能的话,最简单的检查方法是什么?因为时间戳也是允许的。

492892 次浏览

Date.parse()足够吗?

查看它的相对MDN文档页面

如果字符串date有效,Date.parse返回时间戳。下面是一些用例:

// /!\ from now (2021) date interpretation changes a lot depending on the browser
Date.parse('01 Jan 1901 00:00:00 GMT') // -2177452800000
Date.parse('01/01/2012') // 1325372400000
Date.parse('153') // NaN (firefox) -57338928561000 (chrome)
Date.parse('string') // NaN
Date.parse(1) // NaN (firefox) 978303600000 (chrome)
Date.parse(1000) // -30610224000000 from 1000 it seems to be treated as year
Date.parse(1000, 12, 12) // -30610224000000 but days and month are not taken in account like in new Date(year, month,day...)
Date.parse(new Date(1970, 1, 0)) // 2588400000
// update with edge cases from comments
Date.parse('4.3') // NaN (firefox) 986248800000 (chrome)
Date.parse('2013-02-31') // NaN (firefox) 1362268800000 (chrome)
Date.parse("My Name 8") // NaN (firefox) 996616800000 (chrome)

像这样的怎么样?它将测试它是一个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);
}

我应该提到的是,这并不测试ISO格式的字符串,但只要再对RegExp做一些工作,您就可以了。

以下是我如何在我现在正在开发的应用程序中解决这个问题:

根据krillgar的反馈更新:

var isDate = function(date) {
return (new Date(date) !== "Invalid Date") && !isNaN(new Date(date));
}

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 */
}

这是一个极简的版本。

var isDate = function (date) {
return!!(function(d){return(d!=='Invalid Date'&&!isNaN(d))})(new Date(date));
}

是否可以检查一个日期相关的函数是可用的对象,以发现它是否是一个日期对象?

就像

var l = new Date();
var isDate = (l.getDate !== undefined) ? true; false;

2015年更新

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

所以我认为在这里添加一些新的信息是很重要的。我写它是因为我害怕人们会复制粘贴这里发布的一些代码并在生产中使用它。

这里的大多数答案要么使用一些复杂的正则表达式,只匹配一些非常特定的格式,并且实际上做得不正确(比如匹配1月32日,而不匹配广告中的实际ISO日期-参见< >强演示< / >强) 他们试图将任何东西传递给Date构造函数,并希望得到最好的结果。

使用的时刻

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

它是一个用JavaScript解析、验证、操作和显示日期的库,它的API比标准的JavaScript日期处理函数丰富得多。

它是12kB的压缩文件,可以在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

使用Moment可以非常具体地检查有效日期。有时候,添加一些你所期望的格式线索是非常重要的。例如,06/22/2015这样的日期看起来像一个有效日期,除非您使用DD/MM/YYYY格式,在这种情况下,该日期应该作为无效而被拒绝。有几种方法可以告诉Moment你想要什么样的格式,例如:

moment("06/22/2015", "MM/DD/YYYY", true).isValid(); // true
moment("06/22/2015", "DD/MM/YYYY", true).isValid(); // false

true参数存在,因此如果它不符合所提供的格式之一,Moment将不会尝试解析输入(在我看来,这应该是默认行为)。

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

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

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

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

看到:< >强演示< / >强

其他的库

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

2016年更新

我创建了immoment模块,它类似于Moment的(一个子集),但没有由现有对象的突变引起的惊喜(更多信息请参阅的文档)。

2018年更新

今天,我建议使用勒克桑来进行日期/时间操作,而不是Moment,后者(与Moment不同)使所有对象都是不可变的,因此不会出现与日期隐式突变相关的令人讨厌的意外。

更多信息

参见:

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

底线

当然,任何人都可以尝试重新开始,写一个正则表达式(但是实际上在你这样做之前读取了ISO 8601和RFC 3339)或调用带有随机数据的插入构造函数来解析诸如'Invalid Date'(你确定这个消息在所有平台上都是完全一样吗?)在所有地区?你可以使用一个经过测试的解决方案,并利用你的时间来改进它,而不是重新发明它。这里列出的所有库都是开源的免费软件。

我会这样做

var myDateStr= new Date("2015/5/2");


if( ! isNaN ( myDateStr.getMonth() )) {
console.log("Valid date");
}
else {
console.log("Invalid date");
}

在这里

这里的答案都没有提到检查日期是否无效,例如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];
}
这就是我最后怎么做的。这不会涵盖所有格式。 你必须相应地调整。我可以控制格式,所以它适用于我

function isValidDate(s) {
var dt = "";
var bits = [];
if (s && s.length >= 6) {
if (s.indexOf("/") > -1) {
bits = s.split("/");
}
else if (s.indexOf("-") > -1) {
bits = s.split("-");
}
else if (s.indexOf(".") > -1) {
bits = s.split(".");
}
try {
dt = new Date(bits[2], bits[0] - 1, bits[1]);
} catch (e) {
return false;
}
return (dt.getMonth() + 1) === parseInt(bits[0]);
} else {
return false;
}
}

这个可调用函数工作正常,有效日期返回true。 请确保使用ISO格式的日期(yyyy-mm-dd或yyyy/mm/dd)调用:

function validateDate(isoDate) {


if (isNaN(Date.parse(isoDate))) {
return false;
} else {
if (isoDate != (new Date(isoDate)).toISOString().substr(0,10)) {
return false;
}
}
return true;
}

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

if(sDate.toString() == parseInt(sDate).toString()) return false;

这一行是用来剔除数字的。因此,整个函数看起来像这样:

function isDate(sDate) {
if(sDate.toString() == parseInt(sDate).toString()) return false;
var tryDate = new Date(sDate);
return (tryDate && tryDate.toString() != "NaN" && tryDate != "Invalid Date");
}


console.log("100", isDate(100));
console.log("234", isDate("234"));
console.log("hello", isDate("hello"));
console.log("25 Feb 2018", isDate("25 Feb 2018"));
console.log("2009-11-10T07:00:00+0000", isDate("2009-11-10T07:00:00+0000"));

通过参考以上所有的评论,我已经找到了一个解决方案。

如果传递的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");
}

你可以在JSFiddle上播放在这里

使用正则表达式进行验证。

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);
}

好吧,这是一个老问题,但我在检查这里的解时找到了另一个解。For me工作检查函数getTime()是否存在于日期对象:

const checkDate = new Date(dateString);


if (typeof checkDate.getTime !== 'function') {
return;
}

下面是一个只使用Date.parse()的改进函数:

function isDate(s) {
if(isNaN(s) && !isNaN(Date.parse(s)))
return true;
else return false;
}

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

不能持续工作,小心!

isDate('Leyweg 1')在Chrome上返回true (Firefox返回false)🤔

读取:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse(日期。在像这样调用时,会在底层调用:new Date(someDateString)。


最初的回答:

function isDate(dateStr) {
return !isNaN(new Date(dateStr).getDate());
}
  • 这将在任何浏览器上工作,因为它不依赖于“无效日期”;检查。
  • 这将适用于ES6之前的遗留代码。
  • 这将在没有任何库的情况下工作。
  • 这将不管任何日期格式工作。
  • 这并不依赖于Date。当"Spiderman 22"都在日期字符串中。
  • 这并不要求我们编写任何正则表达式。

我觉得没有一个答案正确理解了OP的问题。这里的问题是JavaScript可以将任何数字解析为有效日期,因为Date对象可以将像'3000'这样的字符串解析为年份,并将返回一个有效的date实例:

new Date('3000')


> Wed Jan 01 3000 02:00:00 GMT+0200 (Eastern European Standard Time)

为了解决这个问题,我们可以在严格模式中通过传入第三个参数来使用Day.js库的解析方法。它被记录在他们的字符串+格式页。为了使解析能够基于某种格式工作,我们还必须启用CustomParseFormat插件。我假设你可以在这里使用ESM导入,或者设置一个像Webpack这样的编译器

import dayjs from 'dayjs'
import formatParser from 'dayjs/plugin/customParseFormat'


dayjs.extend(formatParser)


dayjs('3000', 'YYYY-MM-DD', true).isValid()


> false

该函数验证格式为m/d/yyyy或mm/dd/yyyy的输入字符串是否可以转换为日期,并且该日期是与输入字符串匹配的有效日期。添加更多条件检查来验证其他格式。

/**
* Verify if a string is a date
* @param {string} sDate - string that should be formatted m/d/yyyy or mm/dd/yyyy
* @return {boolean} whether string is a valid date
*/
function isValidDate(sDate) {
let newDate = new Date(sDate);
console.log(sDate + " date conversion: " + newDate);
let isDate = (!isNaN(newDate.getTime()));
console.log(sDate + " is a date: " + isDate);
if (isDate) {
let firstSlash = sDate.indexOf("/");
let secondSlash = sDate.indexOf("/",firstSlash+1);
let originalDateString = parseInt(sDate.slice(0,firstSlash),10) + "/" + parseInt(sDate.slice(firstSlash+1,secondSlash),10) + "/" + parseInt(sDate.slice(secondSlash+1),10);
let newDateString = (newDate.getMonth()+1) + "/" + (newDate.getDate()) + "/" + (newDate.getFullYear());
isDate = (originalDateString == newDateString);
console.log(originalDateString + " matches " + newDateString + ": " + isDate);
}
return isDate;
}

我发现这个解决方案非常好:

const DateTime = require('luxon').DateTime;


isDateValid(stringDate) {
let date = DateTime.fromFormat(stringDate, 'd-M-y');
if (date.invalid === null) {
return date.toJSDate();
}
date = DateTime.fromFormat(stringDate, 'd,M,y');
if (date.invalid === null) {
return date.toJSDate();
}
date = DateTime.fromFormat(stringDate, 'y-M-d');
if (date.invalid === null) {
return date.toJSDate();
}
date = DateTime.fromFormat(stringDate, 'y,M,d');
if (date.invalid === null) {
return date.toJSDate();
}
date = DateTime.fromFormat(stringDate, 'y.M.d');
if (date.invalid === null) {
return date.toJSDate();
}
date = DateTime.fromFormat(stringDate, 'd.M.y');
if (date.invalid === null) {
return date.toJSDate();
}
date = DateTime.fromFormat(stringDate, 'y/M/d');
if (date.invalid === null) {
return date.toJSDate();
}
date = DateTime.fromFormat(stringDate, 'd/M/y');
if (date.invalid === null) {
return date.toJSDate();
}
return false;
}


isDateValid('30.12.86'); //true
isDateValid('30/12/86'); //true
isDateValid('86-12-40'); //false

而且您可以轻松地添加更多格式

下面是可以用来验证输入是number或可以转换为date objectstring的方法。

它涵盖以下情况:

  1. 捕获任何导致"Invalid Date" date constructor结果的输入;
  2. 捕捉日期是“有效”的情况;从技术的角度来看,但从业务逻辑的角度来看,它是无效的
  • new Date(null).getTime(): 0
  • new Date(true).getTime(): 1
  • new Date(-3.14).getTime(): -3
  • new Date(["1", "2"]).toDateString(): Tue Jan 02 2001
  • new Date([1, 2]).toDateString(): Tue Jan 02 2001
function checkDateInputValidity(input, lowerLimit, upperLimit) {
// make sure the input is a number or string to avoid false positive correct dates:
if (...) {
return false
}
// create the date object:
const date = new Date(input)
// check if the Date constructor failed:
if (date.toDateString() === 'Invalid Date') {
return false
}
// check if the Date constructor succeeded, but the result is out of range:
if (date < new Date(lowerLimit) || date > new Date(upperLimit)) {
return false
}
return true
}


// const low = '2021-12-31T23:59:59'
// const high = '2025-01-01T00:00:00'

我认为最直接的解决办法是

Date.parse(yourDate) > 0 ? true : false;

如果不是有效日期,则为NaN,即大于0的