我需要用正则表达式验证格式为dd/mm/yyyy的日期字符串。
这个正则表达式验证dd/mm/yyyy,但不验证像31/02/4500这样的无效日期:
^(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-]\d{4}$
什么是有效的正则表达式来验证支持闰年的dd/mm/yyyy格式?
我需要用正则表达式验证格式为dd/mm/yyyy的日期字符串。
这个正则表达式验证dd/mm/yyyy,但不验证像31/02/4500这样的无效日期:
^(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-]\d{4}$
什么是有效的正则表达式来验证支持闰年的dd/mm/yyyy格式?
当前回答
在这里找到这个reg ex
^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$
这将正确地验证mm/dd/yyyy格式和有效日期(但不是m/d/yyyy)。
一些测试
其他回答
另一种答案,根据月(mm)和年(yyyy)验证日(dd)(即,在闰年也验证2月29日),并允许年范围从0001到9999(根据公历,0000是无效年)
^(?:(?:(?:0[1-9]|[12]\d|3[01])/(?:0[13578]|1[02])|(?:0[1-9]|[12]\d|30)/(?:0[469]|11)|(?:0[1-9]|1\d|2[0-8])/02)/(?!0000)\d{4}|(?:(?:0[1-9]|[12]\d)/02/(?:(?!0000)(?:[02468][048]|[13579][26])00|(?!..00)\d{2}(?:[02468][048]|[13579][26]))))$
对于那些看到这些并感到完全困惑的人,这里是我剧本的一段摘录。不幸的是,它所做的只是匹配日期时间输入中的有效数字,31 Feb将被标记为有效,但正如许多人所说,regex真的不是做这个测试的最佳工具。
以'yyyy-MM-dd hh:mm'格式匹配日期(实际上可以按您喜欢的任何顺序匹配)
var dateerrors = false;
var yearReg = '(201[4-9]|202[0-9])'; ///< Allows a number between 2014 and 2029
var monthReg = '(0[1-9]|1[0-2])'; ///< Allows a number between 00 and 12
var dayReg = '(0[1-9]|1[0-9]|2[0-9]|3[0-1])'; ///< Allows a number between 00 and 31
var hourReg = '([0-1][0-9]|2[0-3])'; ///< Allows a number between 00 and 24
var minReg = '([0-5][0-9])'; ///< Allows a number between 00 and 59
var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');
$('input').filter(function () {return this.id.match(/myhtml_element_with_id_\d+_datetime/);}).each(function (e) {
if (e > 0) {
// Don't test the first input. This will use the default
var val = $(this).val();
if (val && !val.trim().match(reg)) {
dateerrors = true;
return false;
}
}
});
if (dateerrors) {
alert('You must enter a validate date in the format "yyyy-mm-dd HH:MM", e.g. 2019-12-31 19:30');
return false;
}
上面的脚本首先构建一个正则表达式对象。然后它会找到id与某个模式匹配的所有输入,然后循环遍历这些输入。我没有测试我找到的第一个输入(if (e > 0))。
稍微解释一下:
var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');
^表示匹配的开始,而$表示匹配的结束。
return this.id.match(/myhtml_element_with_id_\d+_datetime/);
\d+表示匹配单个或连续的整数序列,因此myhtml_element_with_id_56_datetime和myhtml_element_with_id_2_datetime将匹配,但myhtml_element_with_id_5a_datetime将不匹配
我认为最好的方法是使用Moment.js的isValid()方法,指定格式并使用严格的解析。
正如moment.js文档所说
从2.3.0版本开始,您可以为最后一个参数指定一个布尔值 使Moment使用严格解析。严格解析要求 格式和输入完全匹配,包括分隔符。
value = '2020-05-25';
format = 'YYYY-MM-DD';
moment(value, format, true).isValid() // true
这里我为dd/mm/yyyy写了一个,其中分隔符可以是-之一。,/年范围0000-9999。
它处理闰年,是为正则表达式风格设计的,支持查找头,捕获组和反向引用。d/m/yyyy等无效。如果需要,在[-.,/]中添加分隔符
^(?=\d{2}([-.,\/])\d{2}\1\d{4}$)(?:0[1-9]|1\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\d{4}$
测试regex101;作为Java字符串:
"^(?=\\d{2}([-.,\\/])\\d{2}\\1\\d{4}$)(?:0[1-9]|1\\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\\d{4}$"
解释道:
(?x) # modifier x: free spacing mode (for comments)
# verify date dd/mm/yyyy; possible separators: -.,/
# valid year range: 0000-9999
^ # start anchor
# precheck xx-xx-xxxx,... add new separators here
(?=\d{2}([-.,\/])\d{2}\1\d{4}$)
(?: # day-check: non caturing group
# days 01-28
0[1-9]|1\d|[2][0-8]|
# february 29d check for leap year: all 4y / 00 years: only each 400
# 0400,0800,1200,1600,2000,...
29
(?!.02. # not if feb: if not ...
(?!
# 00 years: exclude !0 %400 years
(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)
# 00,04,08,12,...
\d{2}(?:[02468][048]|[13579][26])
)
)|
# d30 negative lookahead: february cannot have 30 days
30(?!.02)|
# d31 positive lookahead: month up to 31 days
31(?=.(?:0[13578]|10|12))
) # eof day-check
# month 01-12
.(?:0[1-9]|1[012])
# year 0000-9999
.\d{4}
$ # end anchor
参见SO正则表达式常见问题解答;如果失败了,请告诉我。
((((0[13578]|1[02])\/(0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)\/(0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)(\/(0[1-9]|1[0-9]|2[0-8]))))\/(19([6-9][0-9])|20([0-9][0-9])))|((02)\/(29)\/(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))
从1960年到2028年是否会验证MM/DD/YYYY格式
如果您需要扩展闰年支持,请添加
19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048]|3[26]|4[048])))
这也是功
^((((0[13578]|1[02])[/](0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)[/](0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)([/](0[1-9]|1[0-9]|2[0-8]))))[/](19([6-9][0-9])|20([0-9][0-9])))|((02)[/](29)[/](19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))
如果可以更改格式mm-dd-yyyy,则将[/]替换为[-] 也可以在线查询http://regexr.com/