Javascript 正则表达式 | 闰年及更多
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8647893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Regular Expression | Leap Years and More
提问by Rion Williams
I've recently been looking for a regular expression to do some client side date checking, and I haven't been able to find one that can satisfy the following criteria:
我最近一直在寻找一个正则表达式来进行一些客户端日期检查,但我一直无法找到满足以下条件的正则表达式:
- Has a range from 1800 - Now
- Performs proper date checking with leap years
- MM/DD/YYYY Form
- Invalid Date Checking
- 范围从 1800 到现在
- 使用闰年执行正确的日期检查
- MM/DD/YYYY 表格
- 无效的日期检查
(These constraints were outside of my scope and are a requirement as per the client, despite my efforts to convince them this wasn't the best route)
(这些限制超出了我的范围,并且是客户的要求,尽管我努力说服他们这不是最佳途径)
Current code:
当前代码:
$('input').keyup(function()
{
var regex = /^(?:(0[1-9]|1[012])[\/.](0[1-9]|[12][0-9]|3[01])[\/.](18|19|20)[0-9]{2})$/;
$(this).toggleClass('invalid',!regex.test($(this).val()));
});
Update:
更新:
I should note that this is primarily to see if a regular expression like this would be possible (as the use of a Regex is not my choice in this matter). I am aware of the other (and better) options for validating a date, however as previously mentioned - this is to see if it was possible through a regular expression.
我应该注意,这主要是为了看看是否可以使用这样的正则表达式(因为在这件事上使用 Regex 不是我的选择)。我知道验证日期的其他(和更好)选项,但是如前所述 - 这是为了查看是否可以通过正则表达式。
回答by McKay
As is mentioned elsewhere, regular expressions almost certanily not what you want. But, having said that, if you really want a regular expression, here is how it is built:
正如其他地方提到的,正则表达式几乎肯定不是你想要的。但是,话虽如此,如果你真的想要一个正则表达式,它是如何构建的:
31 day months
31天月
(0[13578]|1[02])[\/.](0[1-9]|[12][0-9]|3[01])[\/.](18|19|20)[0-9]{2}
30 day months
30天月
(0[469]|11)[\/.](0[1-9]|[12][0-9]|30)[\/.](18|19|20)[0-9]{2}
February 1-28 always valid
2 月 1-28 日始终有效
(02)[\/.](0[1-9]|1[0-9]|2[0-8])[\/.](18|19|20)[0-9]{2}
February 29 also valid on leap years
2 月 29 日也适用于闰年
(02)[\/.]29[\/.](((18|19|20)(04|08|[2468][048]|[13579][26]))|2000)
which means it would be this if you put it all together:
这意味着如果你把它们放在一起会是这样的:
((0[13578]|1[02])[\/.](0[1-9]|[12][0-9]|3[01])[\/.](18|19|20)[0-9]{2})|((0[469]|11)[\/.](0[1-9]|[12][0-9]|30)[\/.](18|19|20)[0-9]{2})|((02)[\/.](0[1-9]|1[0-9]|2[0-8])[\/.](18|19|20)[0-9]{2})|((02)[\/.]29[\/.](((18|19|20)(04|08|[2468][048]|[13579][26]))|2000))
This version is a little shorter, but a little harder to understand.
这个版本有点短,但有点难理解。
((0[13578]|1[02])[\/.]31[\/.](18|19|20)[0-9]{2})|((01|0[3-9]|1[1-2])[\/.](29|30)[\/.](18|19|20)[0-9]{2})|((0[1-9]|1[0-2])[\/.](0[1-9]|1[0-9]|2[0-8])[\/.](18|19|20)[0-9]{2})|((02)[\/.]29[\/.](((18|19|20)(04|08|[2468][048]|[13579][26]))|2000))
These scripts are long and unmaintainable. It should be clear that this isn't a good idea, but it is possible.
这些脚本很长而且无法维护。应该清楚,这不是一个好主意,但它是可能的。
Caveats:
注意事项:
- range 1800-2099 (more can be added without too much difficulty, but requires changes in 4-6 disparate places)
- requires 2 digit months and days (the strictness could be removed from the expression in ~8 places)
[\/.]
as seperators (8 places)- Hasn't been tested (we could check it against all digit combinations and compare with the javascript date function? [proof that we're reinventing the wheel])
- 范围 1800-2099(可以添加更多,没有太多困难,但需要在 4-6 个不同的地方进行更改)
- 需要 2 位数的月和日(可以从表达式中删除 ~8 处的严格性)
[\/.]
作为分隔符(8 个位置)- 尚未经过测试(我们可以对照所有数字组合进行检查并与 javascript 日期函数进行比较?[证明我们正在重新发明轮子])
回答by Jim Mischel
I would suggest that you abandon the attempt to use regular expressions for this. You're much better off parsing the date into its constituent parts (month, day, year), and then using numerical comparisons to make sure it's in the proper range.
我建议您放弃为此使用正则表达式的尝试。最好将日期解析为其组成部分(月、日、年),然后使用数值比较来确保它在正确的范围内。
Better yet, see if the Javascript Date.parsefunction will do what you want.
更好的是,看看 Javascript Date.parse函数是否会做你想要的。
Parsing dates with regular expressions is possible, but frustrating. It's hard to get right, the expression is difficult for non-regex wizards to understand (which means it's difficult to prove that the thing is correct), and it is slowcompared to other options.
使用正则表达式解析日期是可能的,但令人沮丧。很难弄对,表达式对于非正则表达式的向导来说很难理解(这意味着很难证明事情是正确的),并且与其他选项相比速度较慢。
回答by ?ime Vidas
This is how I would do it:
这就是我将如何做到的:
function validate( input ) {
var date = new Date( input );
input = input.split( '/' );
return date.getMonth() + 1 === +input[0] &&
date.getDate() === +input[1] &&
date.getFullYear() === +input[2];
}
Usage:
用法:
validate( '2/1/1983' ) // true
validate( '2/29/1983' ) // false
validate( '2/29/1984' ) // true (1984 is a leap year)
Live demo:http://jsfiddle.net/9QNRx/
现场演示:http : //jsfiddle.net/9QNRx/
回答by Andrew Macheret
Obviously regular expressions are not the ideal way to do this. Also, it's much safer to be working with YYYY-MM-DD
(ISO 8601) format, not MM/DD/YYYY
.
显然,正则表达式不是执行此操作的理想方式。此外,使用YYYY-MM-DD
(ISO 8601) 格式更安全,而不是MM/DD/YYYY
.
That said, here's going for the shortest fully-working regular expression for dates from 01/01/1800 to 12/31/2099:
也就是说,这里是从 1800 年 1 月 1 日到 2099 年 12 月 31 日的最短完整正则表达式:
^(((0[1-9]|1[012])\/(?!00|29)([012]\d)|(0[13-9]|1[012])\/(29|30)|(0[13578]|1[02])\/31)\/(18|19|20)\d{2}|02\/29\/((18|19|20)(0[48]|[2468][048]|[13579][26])|2000))$
Length: 162 characters.
长度:162 个字符。
Breakdown:
分解:
^ # start
(
( # non-leap months & days
(0[1-9]|1[012])/(?!00|29)([012]\d) # all months, days 01-28, uses negative lookahead
|
(0[13-9]|1[012])/(29|30) # all months except feb, days 29,30
|
(0[13578]|1[02])/31 # all 31 day months, day 31 only
)
/
(18|19|20)\d{2} # all years
|
02/29 # leap day
/
(
(18|19|20)(0[48]|[2468][048]|[13579][26]) # leap years not divisible by 100
|
2000 # leap years divisible by 100
)
)
$ # end
Here's a fiddlethat tests all use cases from 00/00/1800 to 99/99/2099.
这是一个测试从 00/00/1800 到 99/99/2099 的所有用例的小提琴。
Also, for more fun, here's another fiddlethat generates the lousiest possible regular expression that still works, 1205306 characters long. It looks something like this:
此外,为了更有趣,这里有另一个小提琴,它生成最糟糕的正则表达式仍然有效,1205306 个字符长。它看起来像这样:
^(01/01/1800|01/02/1800|01/03/1800|...|12/29/2099|12/30/2099|12/31/2099)$
回答by Kuldeep
this regular expression for YYYY-MM-DD format
此正则表达式为 YYYY-MM-DD 格式
((18|19|20)[0-9]{2}[\-.](0[13578]|1[02])[\-.](0[1-9]|[12][0-9]|3[01]))|(18|19|20)[0-9]{2}[\-.](0[469]|11)[\-.](0[1-9]|[12][0-9]|30)|(18|19|20)[0-9]{2}[\-.](02)[\-.](0[1-9]|1[0-9]|2[0-8])|(((18|19|20)(04|08|[2468][048]|[13579][26]))|2000)[\-.](02)[\-.]29
回答by Ravi Kiran
^(((?:(?:1[6-9]|[2-9]\d)?\d{2})(-)(?:(?:(?:0?[13578]|1[02])(-)31)|(?:(?:0?[1,3-9]|1[0-2])(-)(?:29|30))))|(((?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))(-)(?:0?2(-)29))|((?:(?:(?:1[6-9]|[2-9]\d)?\d{2})(-)(?:(?:0?[1-9])|(?:1[0-2]))(-)(?:0[1-9]|1\d|2[0-8]))))$
Please try the above Reg Expression. I tried multiple combinations and found to be working.
请尝试上面的 Reg 表达式。我尝试了多种组合并发现有效。
Please check if this works for you too.
请检查这是否也适合您。
Format Accepted : YYYY-MM-DD
接受的格式:YYYY-MM-DD
Year accepted from 1600
从 1600 年开始接受的年份
回答by MilapTank
Hello Find RegEx for your Requirement
您好,根据您的要求查找 RegEx
- Has a range from 1800
- Now Performs proper date checking with leap years
- DD/MM/YYYY Format
- Invalid Date Checking
- 范围从 1800
- 现在使用闰年执行正确的日期检查
- DD/MM/YYYY 格式
- 无效的日期检查
^(?:(?:31(/)(?:0[13578]|1[02]))\1|(?:(?:29|30)(/)(?:0[13-9]|1[0-2])\2))(?:(?:18|19|20)\d{2})$|^(?:29(/)02\3(?:(?:(?:(?:18|19|20))(?:0[48]|[2468][048]|[13579][26]))))$|^(?:0?[1-9]|1\d|2[0-8])(/)(?:(?:0[1-9])|(?:1[0-2]))\4(?:(?:18|19|20)\d{2})$
^(?:(?:31(/)(?:0[13578]|1[02]))\1|(?:(?:29|30)(/)(?:0[13-9] |1[0-2])\2))(?:(?:18|19|20)\d{2})$|^(?:29(/)02\3(?:(?:( ?:(?:18|19|20))(?:0[48]|[2468][048]|[13579][26]))))$|^(?:0?[1-9] |1\d|2[0-8])(/)(?:(?:0[1-9])|(?:1[0-2]))\4(?:(?:18| 19|20)\d{2})$
Image and debug RegEx At https://www.debuggex.com/
图像和调试 RegEx 在https://www.debuggex.com/
Testing:
测试:
- DD/MM/YYYY
01/12/190Not Match29/02/1903Not Match37/02/1903Not Match09/03/1703Not Match09/03/2103Not Match09/31/2103Not Match- 29/02/1904 - Match
- 01/12/1988 - Match
- 日/月/年
01/12/190不匹配29/02/1903不匹配37/02/1903不匹配09/03/1703不匹配09/03/2103不匹配09/31/2103不匹配- 29/02/1904 - 比赛
- 01/12/1988 - 比赛
回答by mkaj
Using moment (not regex) I've done the following:
使用时刻(不是正则表达式)我做了以下事情:
Assuming you have an ISO date as a string value:
假设您有一个 ISO 日期作为字符串值:
var isoDate = '2016-11-10';
var parsedIsoDate = moment(isoDate, ['YYYY-MM-DD'], true).format('YYYY-MM-DD');
if (parsedIsoDate !== isoDate) {
// Invalid date.
}
回答by hex494D49
This is the RegEx I use for date validation on client-side. It has a range from 1000 to 2999, validates leap years and optionally the time part. Isn't it gorgeous :)
这是我用于客户端日期验证的 RegEx。它的范围从 1000 到 2999,验证闰年和可选的时间部分。是不是很漂亮:)
var r = /^(0[1-9]|1\d|2[0-8]|29(?=-\d\d-(?!1[01345789]00|2[1235679]00)\d\d(?:[02468][048]|[13579][26]))|30(?!-02)|31(?=-0[13578]|-1[02]))-(0[1-9]|1[0-2])-([12]\d{3})(\s([01]\d|2[0-3]):([0-5]\d):([0-5]\d))?$/gm;
r.test('20-02-2013 10:01:07'); // true
r.test('29-02-1700'); // false
r.test('29-02-1604 14:01:45'); // true
r.test('29-02-1900 20:10:50'); // false
r.test('31-12-2000'); // true
r.test('31-11-2008 05:05:05'); // false
r.test('29-02-2004 05:01:23'); // true
r.test('24-06-2014 24:10:05'); // false
回答by Daniel O'Hara
I was trying to validate YYYY-MM-DD, where YYYY can be two digit and MM and DD can be one. This is what I came up with. It treats all centuries as leap years.
我试图验证 YYYY-MM-DD,其中 YYYY 可以是两位数,MM 和 DD 可以是一位。这就是我想出的。它将所有世纪视为闰年。
((\d\d)?\d\d-((0?(1|3|5|7|8)|10|12)-(31|30|[21]\d|0?[1-9])|(0?(4|6|9)|11)-(31|30|[21]\d|0?[1-9])|0?2-((2[0-8]|1\d)|0?[1-9]))|(\d\d)?((0|2|4|6|8)(0|4|8)|(1|3|5|7|9)(2|6))-0?2-29)