我已经创建了这样的正则表达式:
(((([1-9]|1[0-9]|2[0-8])[-]([1-9]|1[0-2]))|((29|30|31)[-]([13578]|1[02]))|((29|30)[-]([469]|11)))[-]([0-9][0-9][0-9][0-9]))|(29[-]2[-](([0-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)))
直到那些日期,一切都很顺利:
29-2-2017(匹配9-2-2017)
31-11-2017(匹配1-11-2017)
它们不存在或当前年份没有飞跃。如何才能使它们与正确匹配?
下面的工作示例: https://regex101.com/r/mjfoAH/2
修改
我最终设法编辑我的正则表达式以匹配我需要的格式。这是为了下一代:
((((\b[1-9]\b|1[0-9]|2[0-8])[-]([1-9]|1[0-2]))|((29|30|31)[-]([13578]|1[02]))|((29|30)[-]([469]|11)))[-]([0-9][0-9][0-9][0-9]))|(29[-]2[-](([0-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)))
工作示例:https://regex101.com/r/mjfoAH/3
P.S。关于可能的重复 - 发布的主题是关于另一种日期格式的正则表达式。也回答检查那里正确不关心闰年。这就是我创建这个主题的原因。
答案 0 :(得分:1)
根据我的评论,我在answer上写了this post来处理日期和闰年。正则表达式可根据您的需求进行配置。下面我已经做了一些调整来创建一个适用于你的格式的正则表达式。
(?(DEFINE)
(?# Date )
(?# Day ranges )
(?<d_day28>0[1-9]|1\d|2[0-8]|[1-9])
(?<d_day29>0[1-9]|1\d|2\d|[1-9])
(?<d_day30>0[1-9]|1\d|2\d|30|[1-9])
(?<d_day31>0[1-9]|1\d|2\d|3[01]|[1-9])
(?# Month specifications )
(?<d_month28>0?2)
(?<d_month29>0?2)
(?<d_month30>0?[469]|11)
(?<d_month31>0?[13578]|1[02])
(?# Year specifications )
(?<d_year>\d+)
(?<d_yearLeap>(?:\d*?(?:(?:0[48]|[13579][26]|[2468][048])|(?:(?:[02468][048]|[13579][26])00))|[48]00|[48])(?=\D|\b))
(?# Valid date formats )
(?<d_format>
(?&d_day28)-(?&d_month28)-(?&d_year)|
(?&d_day29)-(?&d_month29)-(?&d_yearLeap)|
(?&d_day30)-(?&d_month30)-(?&d_year)|
(?&d_day31)-(?&d_month31)-(?&d_year)
)
)
\b(?&d_format)\b
\b(?:(?:0[1-9]|1\d|2[0-8]|[1-9])-(?:0?2)-(?:\d+)|(?:0[1-9]|1\d|2\d|[1-9])-(?:0?2)-(?:(?:\d*?(?:(?:0[48]|[13579][26]|[2468][048])|(?:(?:[02468][048]|[13579][26])00))|[48]00|[48])(?=\D|\b))|(?:0[1-9]|1\d|2\d|30|[1-9])-(?:0?[469]|11)-(?:\d+)|(?:0[1-9]|1\d|2\d|3[01]|[1-9])-(?:0?[13578]|1[02])-(?:\d+))\b
下面我已经从链接的帖子中复制了解释(我在另一个问题上的答案)。解释几乎相同(减去时间属性)
我将解释第一个版本,因为第二个版本只是一个 它的缩小版本。请注意,可以轻松更改正则表达式 适应更多格式(只有1种格式,略有变化 被接受,但这是一个非常可定制的正则表达式。
- d_days28 :匹配
中的任何数字01
至28
- d_days29 :匹配
中的任何数字01
至29
- d_days30 :匹配
中的任何数字01
到30
- d_days31 :匹配
中的任何数字01
至31
- d_month28 :匹配可能只有 28 天的月份(2月 - 因此
02
)- d_month29 :匹配可能只有 29 天的月份(2月 - 因此
02
)- d_month30 :匹配仅 30 天的月份(4月,6月,9月,11月 - 因此
04, 06, 09, 11
)- d_month31 :匹配仅 31 天的月份(1月,3月,5月,7月,8月,10月,12月 - 因此
01, 03, 05, 07, 08, 10, 12
)- d_year :匹配任何一年(必须至少有一位数
\d
)- d_yearLeap :为了更清晰,我会将其划分为多个细分
\d*?
- 匹配任意数量的数字,但尽可能少
- 匹配以下其中一项
(?:(?:(?!00)[02468][048]|[13579][26])|(?:(?:[02468][048]|[13579][26])00))
- 匹配以下其中一项
(?:(?!00)[02468][048]|[13579][26])
- 匹配以下其中一项
- 其中一个
02468
,其次是048
,但不是00
- 之一
13579
之一,后跟26
(?:(?:[02468][048]|[13579][26])00)
- 匹配以下其中一项,然后是00
- 之一
02468
之一,后跟048
- 之一
13579
之一,后跟26
[48]00
- 匹配400
或800
[48]
- 匹配4
或8
(?=\D|\b)
- 确保以下内容为非数字字符\D
或字边界字符\b
- d_format :这指向以前的群组,以确保正确格式化月份并匹配天/月和 天/年(闰年)要求,以便我们确保正确的日期 验证
- t_period :如果其他人需要此功能以进行验证,则会添加此选项
- 确保期间为
am, pm, a.m, p.m
或其各自的大写版本(包括a.M
等内容 使用多个案例)- t_hours12 :匹配
的任何小时00
到11
- t_hours24 :匹配
的任何小时00
到23
- t_minutes :匹配从
00
到59
的所有分钟- t_seconds :匹配从
00
到59
的任何秒数- t_milliseconds :匹配任意3位数(
000
至999
)- t_format :这指向以前的群组,以确保时间格式正确。我添加了额外的时间设置(如 以及其他人的加法,包括毫秒和时间段。 使用)
- dt_format :要检查的日期时间格式(在您的情况下,
date time
- 按空格字符分隔)
- 定义块后面是
\b(?&dt_format)\b
,它只是匹配上面指定的dt_format
,确保前面和后面的内容 取代它是一个单词边界字符(或没有字符)\b
闰年
进一步了解正则表达式的闰年部分......
我假设以下内容:
- 所有年份不闰年,除非以下情况属实
- ((年份模
4
为0
) AND (年模100
不是0
))或(年模400
为0
)- 来源:leap year calculation
- 闰年一直存在(至少从第1年开始) - 因为我不想开始假设并做更多的研究。
正则表达式通过确保:
起作用
- 以
0, 4, 8
结尾的所有闰年先于0, 2, 4, 6, 8
(所有这些在模数后都会导致0
- &gt;即{{1 }})- 以
24 % 4 = 0
结尾的所有闰年都在**前面2, 6
(所有这些都在1, 3, 5, 7, 9
之后产生模数 - &gt;即0
)< / LI>- 以
32 % 4 = 0
结尾的所有闰年,以及为1和2。的所有闰年均被否定(00
执行此操作)- 以
(?!00)
结尾的所有闰年在之后 。和2. (自00
以来完全一样 - 没有什么需要改变的 除最后两位数外)- 添加年份
醇>4 * 100 = 400
,因为他们不满足上述任何条件
答案 1 :(得分:0)
第一次发布内部编辑部分的相同信息
我最终设法编辑我的正则表达式以匹配我需要的格式。这是为了下一代:
((((\b[1-9]\b|1[0-9]|2[0-8])[-]([1-9]|1[0-2]))|((29|30|31)[-]([13578]|1[02]))|((29|30)[-]([469]|11)))[-]([0-9][0-9][0-9][0-9]))|(29[-]2[-](([0-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)))