使用正则表达式验证日期格式dd/mm/YYYY、dd-mm-YYYY、dd.mm.YYYY、dd mmm YYYY、dd-mmm-YYYY、dd/mmm/YYYY、dd.mmm.YYYY,并支持闰年。

260

我需要使用正则表达式验证日期字符串的格式为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格式?


3
我认为,如果您设置一个准确的期望值,可能会有所帮助,因为此正则表达式实际上并没有正确验证闰年;例如,2013年没有2月29日,但是此正则表达式声称这是有效的:http://regexr.com?346fp - TML
11
为什么要用正则表达式?还有更简单(且更准确)的方法... - Dan Puzey
3
正则表达式用于匹配模式,而不是检查数字值。使用正则表达式找到一个可能的字符串,然后在您所使用的托管语言(如PHP等)中检查其数值。 - Andy Lester
3
此答案已添加到 Stack Overflow 正则表达式 FAQ 中的“常见验证任务”下。 - aliteralmind
4
你错了。正则表达式是验证的最佳工具,因为HTML5输入有一个名为“pattern”的属性,它接受一个正则表达式,浏览器会自动根据正则表达式进行验证,而无需使用任何JavaScript。只需在pattern属性中设置一个正则表达式即可。 - awe
显示剩余6条评论
28个回答

5
以下表达式简单易操作:
((((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[0-9]|1[0-4])))|((02)(\/|-|.)(29)(\/|-|.)(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26])))

它根据 MM/dd/YYYY 格式进行验证,并允许从 1960 年至 2016 年支持闰年。如果您需要扩展闰年支持,只需操作表达式的这部分:

(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]))

希望这对你有很大帮助。


5
"^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((19|20)\\d\\d)$"

将验证任何在1900-2099之间的日期。


3

另一个答案可以根据月份(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]))))$

1
不验证 18/05/0017 - user7917367

2

进一步扩展了由@AlokChaudhary提供的正则表达式,以支持:

1. dd mmm YYYY(除了dd-mmm-YYYYdd/mmm/YYYYdd.mmm.YYYY之外)。

2. 所有字母都是大写的格式(除了标题格式)

dd mmm YYYY例如30 Apr 202624 DEC 2028很受欢迎。

扩展的正则表达式:

(^(?:(?:(?:31(?:(?:([-.\/])(?:0?[13578]|1[02])\1)|(?:([-.\/ ])(?:Jan|JAN|Mar|MAR|May|MAY|Jul|JUL|Aug|AUG|Oct|OCT|Dec|DEC)\2)))|(?:(?:29|30)(?:(?:([-.\/])(?:0?[13-9]|1[0-2])\3)|(?:([-.\/ ])(?:Jan|JAN|Mar|MAR|Apr|APR|May|MAY|Jun|JUN|Jul|JUL|Aug|AUG|Sep|SEP|Oct|OCT|Nov|NOV|Dec|DEC)\4))))(?:(?:1[6-9]|[2-9]\d)?\d{2}))$|^(?:29(?:(?:([-.\/])(?:0?2)\5)|(?:([-.\/ ])(?:Feb|FEB)\6))(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))$|^(?:(?:0?[1-9]|1\d|2[0-8])(?:(?:([-.\/])(?:(?:0?[1-9]|(?:1[0-2])))\7)|(?:([-.\/ ])(?:Jan|JAN|Feb|FEB|Mar|MAR|May|MAY|Jul|JUL|Aug|AUG|Oct|OCT|Dec|DEC)\8))(?:(?:1[6-9]|[2-9]\d)?\d{2}))$)

Regex Demo中包含的测试用例:

功能(保留):

  • 闰年检查(Feb 29 验证),其逻辑为:(能被4整除但不能被100整除) 或 (能被400整除)
  • 支持1600年至9999年
  • 支持dd/mm/YYYYdd-mm-YYYYdd.mm.YYYY(但不支持dd mm YYYY
  • 支持dd mmm YYYYdd-mmm-YYYYdd/mmm/YYYYdd.mmm.YYYYdd mmm YYYY是新添加的。mmm可以是大写,例如DEC或标题格式,例如Dec)

一些额外的小改动如下:

  1. 在2019年2月14日,Ofir Luzon修复了正则表达式中的一个逗号,以允许像29-0,-11这样的日期[错误被复制到Alok Chaudhary的正则表达式中]

  2. (\/|-|\.)替换为([-.\/]),以最小化反斜杠的使用。为了支持一些正则表达式风格(例如PCRE(PHP)),仍然使用\/,尽管其他一些正则表达式风格(例如Python)只需在字符类[ ]中使用/

  3. 添加了一对括号(),将整个正则表达式括起来作为匹配字符串的捕获组。这对于使用findAll类型函数获取匹配项目列表的人非常有用(例如Python中的re.findall)。这使我们能够捕获多行字符串中的所有匹配字符串,使用以下代码:

re.findall示例代码:

match_list = re.findall(regex, source_string)
for item in match_list:
    print(item[0])

扩展正则表达式图像: 在此输入图片描述

感谢为我们所有人创建如此出色的正则表达式的Ofir Luzon和Alok Chaudhary!


2

我认为最好的方法是使用Moment.js的isValid()方法,指定格式并使用严格解析。

正如moment.js文档所说:

从2.3.0版本开始,您可以为最后一个参数指定布尔值,以使Moment使用严格解析。 严格解析要求格式和输入完全匹配,包括分隔符。

value = '2020-05-25';
format = 'YYYY-MM-DD';
moment(value, format, true).isValid() // true

1

Python的简单函数

def is_valid_date(date_text):
    pattern = re.compile('\d{4}-\d{2}-\d{2}$')
    return pattern.match(date_text)

1
我正在使用一个仅接受 MM/DD/YYYY 格式的 API。我找不到其他帖子能像Ofir's answer那样解释闰年,所以我进行了一些修改,并在此重新发布,供需要的人参考。
/^(?:(?:(?:0[13578]|1[02])(\/)31)\1|(?:(?:0[1,3-9]|1[0-2])(\/)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:02(\/)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/)(?:0[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/

1
请按照以下表达式。
Regex regex = new Regex(@"(((0|1)[0-9]|2[0-9]|3[0-1])\/(0[1-9]|1[0-2])\/((19|20)\d\d))$");

1
这个匹配的是 00/00/000099/56/0001,不确定它们是否是有效的日期!! - Toto

1
import re
expression = "Nov 05 20:10:09 2020"
reg_ex = r'((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-2][0-9]|(3)[0-1]) (([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])) (\d{4}))'
assert re.fullmatch(reg_ex, expression), True

关于给定示例的说明

  • Nov = 可能月份组,即(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
  • 05 = 有效日期组,即([0-2][0-9]|(3)[0-1])
  • 20:10:09 = 获取有效小时的组:([0-1][0-9]|2[0-3])、分钟:([0-5][0-9])和秒:([0-5][0-9])
  • 2020 = 获取年份的组,即(\d{4})

2
虽然这段代码可能解决了问题,但是加上解释说明为什么这样做可以解决问题会更有助于提高您的帖子质量,并且可能会得到更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请编辑您的答案以添加解释,并指出适用的限制和假设。 - SherylHohman
@PareshMangukiya:这个答案里没有链接。 - Jeremy Caney

1

如果您正在寻找特定格式,基于Alok的答案,这对“dd / MM / yyyy”和“dd / MMM / yyyy”日期格式有效。

function isValidDateFormatDDMMYYYY(inputDate) {
    var date_regex = /^(?:(?:31(\/)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/;
    return date_regex.test(inputDate);
}

以下是几个通过此代码的示例 -

  • isValidDateFormatDDMMYYYY("15/01/1999") // 返回True
  • isValidDateFormatDDMMYYYY("15/Jan/1999") // 返回True
  • isValidDateFormatDDMMYYYY("15/1/1999") // 返回True
  • isValidDateFormatDDMMYYYY("1/15/1999") // 返回False

谢谢


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接