^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$
可以匹配格式为yyyy-mm-dd的日期,并且兼容四种分割符,它匹配的范围是1900-01-01到2099-12-31。这个表达式的前后都使用了位置字符以确保整个字符串仅包含一个完整的日期。
年份匹配
我们使用(19|20)\d\d
来匹配日期中的年份,这个表达使用选择符来确保年份的前两位是19或者20。注意这里的圆括号的必须的,如果省略了圆括号这个表达式会匹配19或者除了19以外的表达式,即2000-01-01到2099-12-31之间的日期。圆括号是唯一可以防止选择符把整个表达式一分为二的方法。
月份匹配
月份匹配使用0[1-9]|1[012]
,同样它的外面也有圆括号包围,因为选择符|
会把整个表达式一分为二。在第一个选项0[1-9]
中,我们使用了字符集,它可以匹配01到09之间的数字。第二个选项1[012]
可以匹配10、11、12。
日期匹配
日期的匹配包含三个选项。第一个选项0[1-9]
匹配01到09,第二个选项[12][0-9]
匹配10到29,第三个选项3[01]
匹配30到31。
灵活的使用选择符可以避免匹配到不合法的日期,例如2000-00-00。但是这个表达式并没有考虑每个月份的长度,例如2003-02-31是一个不合法的日期。
这个表达式还存在另一个漏洞:日期中的分隔符可以不相同,例如1999/01-01。你可以使用回溯引用来解决这个问题。表达式为^(19|20)\d\d([- /.])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$
。
复杂性与准确性的权衡
我们应该根据使用场景的不同来合理的权衡正则表达式的复杂性与准确性。如果我们验证的数据来源与用户的输入,那么使用上面这个表达式是不够准确的,我们需要使用程序来进一步校验用户的输入。例如我们可以使用脚本语言来判断当前是否是润年,并且对2月29日做特殊处理。
一下是如何使用JavaScript来准确匹配日期
function isvaliddate(date) {
const input = null;
if (input = date.match(/^((?:19|20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$/)) {
// input[1]:年份,input[2]:月份,input[3]:日期
if (input[3] == 31
&& (input[2] == 4 || input[2] == 6 || input[2] == 9 || input[2] == 11)) {
return false; // 4、6、9、11月没有31日
} eles if ($3 >= 30 && $2 == 2) {
return false; // 2月没有30、31日
} eles if ($2 == 2
&& $3 == 29 && !($1 % 4 == 0 and ($1 % 100 != 0 or $1 % 400 == 0))) {
return false; // 只有润年的2月才有29日
} else {
return true; // 日期合法
}
} else {
return false;
}
}
如果文章出现错误,请给我提Issues - -
Github地址