我需要用正则表达式验证格式为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格式?


当前回答

我认为最好的方法是使用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正则表达式常见问题解答;如果失败了,请告诉我。

^(((([13578]|0[13578]|1[02])[-](0[1-9]|[1-9]|1[0-9]|2[0-9]|3[01]))|(([469]|0[469]|11)[-]([1-9]|1[0-9]|2[0-9]|3[0]))|((2|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])))

这个正则表达式将验证日期的格式:

12-30-2016 (mm-dd-yyyy)或12-3-2016 (mm-d-yyyy)或 1-3-2016 (m-d-yyyy)或1-30-2016 (m-dd-yyyy)

你粘贴的正则表达式没有正确地验证闰年,但在同一篇文章中有一个正则表达式。 我将其修改为dd/mm/yyyy, dd-mm-yyyy或dd.mm.yyyy。

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\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])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

我在Arun提供的答案和这里的链接中测试了一下,它似乎有效。

编辑2019年2月14日:我已经删除了正则表达式中允许29-0,-11等日期的逗号

进一步扩展了@AlokChaudhary给出的正则表达式,以支持:

1. dd mmm YYYY(除了dd-mmm-YYYY, dd/mmm/YYYY, dd.mmm.YYYY)。

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

dd mmm YYYY,例如2026年4月30日或2028年12月24日是流行的。

扩展正则表达式:

(^(?:(?:(?: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演示中包含的测试用例

特性(保留):

闰年检查(2月29日验证)包括以下逻辑:(能被4整除但不能被100整除)或(能被400整除) 支持1600 ~ 9999年 支持dd/mm/YYYY、dd-mm-YYYY、dd.mm.YYYY(不支持dd mm YYYY) 支持dd mmm YYYY、dd-mmm-YYYY、dd/mmm/YYYY、dd.mmm.YYYY(新增dd mmm YYYY)。mmm可以是大写的,如DEC或标题格式,如DEC)

一些额外的小润色如下:

Included the fix by Ofir Luzon on February 14th 2019 to remove a comma that was in the regex which allowed dates like 29-0,-11 [error replicated to Alok Chaudhary's regex] Replaced (\/|-|\.) by ([-.\/]) to minimize the use of backslash. \/ is still used in order to support some regex flavor e.g. PCRE(PHP) although some other regex flavor e.g. Python can simply use / inside the character class [ ] Added a pair of parenthesis () surrounding the whole regex to make it a capturing group for the whole matching string. This is useful for people using findAll type of functions to get a matching item list (e.g. re.findall in Python). This enable us to capture all the matching strings within a mult-line string with the following codes:

Re.findall示例代码:

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

扩展正则表达式图像:

应该归功于Ofir Luzon和Alok Chaudhary,他们为我们所有人创造了如此优秀的正则表达式!

我知道这个问题已经有很长时间没有回答了,但也许这可以帮助到其他人。问题是,我也想检查年份,让一些过去的年份也匹配。这个正则表达式匹配日期格式为“DD-MM-YYYY”。所以这个函数将返回一个正则表达式:

const check_year = "01-01-2021" console.log(get_regex()) console.log(check_year.match(get_regex())) function get_regex(){ let actual_year = `${new Date().getFullYear()}` let regex = new RegExp() let split_year = actual_year.split("") let year_regex = `${split_year[0]}[0-${split_year[1]}][0-${split_year[2]}][0-${split_year[3]}]$` let day_month_regex = "^([1-2][0-9]|3[0-1]|0?[1-9])[-]([1][0-2]|0?[1-9])[-]" regex.compile(day_month_regex+year_regex, "g") return regex }