标准:
能被 4 整除的每一年都是闰年,除非它能被 100 整除,除非它能被 400 整除。所以:
2004 - leap year - divisible by 4
1900 - not a leap year - divisible by 4, but also divisible by 100
2000 - leap year - divisible by 4, also divisible by 100, but divisible by 400
二月闰年有 29 天,非闰年有 28 天
4 月、6 月、9 月和 11 月 30 天
一月、三月、五月、七月、八月、十月和十二月共 31 天
测试:
以下日期均应通过验证:
1976-02-29
2000-02-29
2004-02-29
1999-01-31
以下日期均应未通过验证:
2015-02-29
2015-04-31
1900-02-29
1999-01-32
2015-02-00
范围:
我们将测试从 1000 年 1 月 1 日到 2999 年 12 月 31 日的日期。从技术上讲,目前使用的公历仅在 1753 年用于大英帝国,并在 1600 年代的不同年份用于欧洲国家,但是我不会担心这个。
正则表达式测试闰年:
能被 400 整除的年份:
1200|1600|2000|2400|2800
can be shortened to:
(1[26]|2[048])00
if you wanted all years from 1AD to 9999 then this would do it:
(0[48]|[13579][26]|[2468][048])00
if you're happy with accepting 0000 as a valid year then it can be shortened:
([13579][26]|[02468][048])00
能被 4 整除的年份:
[12]\d([02468][048]|[13579][26])
能被 100 整除的年份:
[12]\d00
不能被 100 整除:
[12]\d([1-9]\d|\d[1-9])
能被 100 整除但不能被 400 整除的年份:
((1[1345789])|(2[1235679]))00
能被 4 整除,但不能被 100 整除:
[12]\d([2468][048]|[13579][26]|0[48])
闰年:
divisible by 400 or (divisible by 4 and not divisible by 100)
((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48])
不能被 4 整除:
[12]\d([02468][1235679]|[13579][01345789])
不是闰年:
Not divisible by 4 OR is divisible by 100 but not by 400
([12]\d([02468][1235679]|[13579][01345789]))|(((1[1345789])|(2[1235679]))00)
有效月份和日期不包括二月(MM-DD):
((01|03|05|07|08|10|12)-(0[1-9]|[12]\d|3[01]))|((04|06|09|11)-(0[1-9]|[12]\d|30))
shortened to:
((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30))
2 月 28 天:
02-(0[1-9]|1\d|2[0-8])
二月有 29 天:
02-(0[1-9]|[12]\d)
有效日期:
(leap year followed by (valid month-day-excluding-february OR 29-day-february))
OR
(non leap year followed by (valid month-day-excluding-february OR 28-day-february))
((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8]))))
所以你有一个 1000 年 1 月 1 日到 2999 年 12 月 31 日之间日期的正则表达式,格式为 YYYY-MM-DD。
我怀疑它可以缩短很多,但我会留给其他人。
这将匹配所有有效日期。如果您希望它仅在仅包含一个日期而不包含其他任何内容时才有效,则将其包装在 ^( )$ 中,如下所示:
^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$
如果您希望它作为可选的日期条目(即它可以是空白或有效日期),则在开头添加 ^$|,如下所示:
^$|^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$