我需要用正则表达式验证格式为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格式?
当前回答
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
对给定例子的解释
11月=一组可能的月份,即(Jan|Feb|Mar|Apr|五月|六月|七月|八月|九月|十月|十一月|十二月) 05年=天即一组有效。([0 - 9][0]| (3)(0 - 1)) 20:10:09 =获得有效时间:一组([0 - 9][0 - 1]| 2(0 - 3)),分钟:([0 - 9][0 - 5])和秒:([0 - 9][0 - 5]) 2020 =获取年份的一组,即(\d{4}))
其他回答
你粘贴的正则表达式没有正确地验证闰年,但在同一篇文章中有一个正则表达式。 我将其修改为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等日期的逗号
我怀疑,在不知道用户的地区何时从儒略历切换到格里高利历的情况下,以下内容是尽可能准确的。
它接受'-','/',或者什么都不作为年,月和日之间的分隔符,不管顺序如何。
MMddyyyy:
^(((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))[-/]?[0-9]{4}|02[-/]?29[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$
ddMMyyyy:
^(((0[1-9]|[12][0-9]|30)[-/]?(0[13-9]|1[012])|31[-/]?(0[13578]|1[02])|(0[1-9]|1[0-9]|2[0-8])[-/]?02)[-/]?[0-9]{4}|29[-/]?02[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$
yyyyMMdd:
^([0-9]{4}[-/]?((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00)[-/]?02[-/]?29)$
除了顺序,这些都精确到儒略历(每四年闰年),直到1700年,当公历与儒略历背离。它有两个问题:
It accepts the year 0000, which doesn't exist in many, but not all, standards. Note that ISO 8601 does accept year 0000 (equivalent to 1 BCE). It doesn't skip the 10-13 days which were lost when the Gregorian Calendar came into use. This varies by locality though. For example, the Roman Catholic Church skipped 10 days, October 5th through October 14th, 1582, but Greece (the last to switch) skipped February 16th through the 28th of 1923, 13 days, having to take into account the leap years of 1700, 1800, and 1900.
从0001年到9999年的Java日历实现已经测试了这一点,唯一的差异是上面提到的1582年的10天。
我认为最好的方法是使用Moment.js的isValid()方法,指定格式并使用严格的解析。
正如moment.js文档所说
从2.3.0版本开始,您可以为最后一个参数指定一个布尔值 使Moment使用严格解析。严格解析要求 格式和输入完全匹配,包括分隔符。
value = '2020-05-25';
format = 'YYYY-MM-DD';
moment(value, format, true).isValid() // true
我已经根据我的要求扩展了@Ofir Luzon给出的格式dd-mmm-YYYY, dd/mmm/YYYY, dd.mmm.YYYY。任何有同样要求的人都可以参考这个
^(?:(?: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})$
并在这里测试了一些测试用例https://regexr.com/39tr1。
为了更好地理解这个正则表达式,请参考下面的图片:
Edit
将其扩展为yyyy/mm/dd、yyyy-mm-dd或yyyy.mm.dd 一些测试用例https://regex101.com/r/3TZfyU/1
^(?:(?:1[6-9]|[2-9]\d)?\d{2})(?:(?:(\/|-|\.)(?:0?[13578]|1[02])\1(?:31))|(?:(\/|-|\.)(?:0?[13-9]|1[0-2])\2(?:29|30)))$|
^(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\/|-|\.)0?2\3(?:29)$|
^(?:(?:1[6-9]|[2-9]\d)?\d{2})(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:0?[1-9]|1\d|2[0-8])$
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
对给定例子的解释
11月=一组可能的月份,即(Jan|Feb|Mar|Apr|五月|六月|七月|八月|九月|十月|十一月|十二月) 05年=天即一组有效。([0 - 9][0]| (3)(0 - 1)) 20:10:09 =获得有效时间:一组([0 - 9][0 - 1]| 2(0 - 3)),分钟:([0 - 9][0 - 5])和秒:([0 - 9][0 - 5]) 2020 =获取年份的一组,即(\d{4}))