d / m / yyyy的正则表达式与闰年

时间:2017-11-21 13:41:50

标签: regex date

我已经创建了这样的正则表达式:

(((([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。关于可能的重复 - 发布的主题是关于另一种日期格式的正则表达式。也回答检查那里正确不关心闰年。这就是我创建这个主题的原因。

2 个答案:

答案 0 :(得分:1)

根据我的评论,我在answer上写了this post来处理日期和闰年。正则表达式可根据您的需求进行配置。下面我已经做了一些调整来创建一个适用于你的格式的正则表达式。

代码

正则表达式(带定义结构)

See regex in use here

(?(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

正则表达式(没有定义构造/单行)

See regex in use here

\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 :匹配0128
  • 中的任何数字   
  • d_days29 :匹配0129
  • 中的任何数字   
  • d_days30 :匹配0130
  • 中的任何数字   
  • d_days31 :匹配0131
  • 中的任何数字   
  • 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 - 匹配400800
      •   
      • [48] - 匹配48
      •   
    •   
    • (?=\D|\b) - 确保以下内容为非数字字符\D或字边界字符\b
    •   
  •   
  • d_format :这指向以前的群组,以确保正确格式化月份并匹配天/月和   天/年(闰年)要求,以便我们确保正确的日期   验证
  •   
  • t_period :如果其他人需要此功能以进行验证,则会添加此选项      
        
    • 确保期间为am, pm, a.m, p.m或其各自的大写版本(包括a.M等内容   使用多个案例)
    •   
  •   
  • t_hours12 :匹配0011
  • 的任何小时   
  • t_hours24 :匹配0023
  • 的任何小时   
  • t_minutes :匹配从0059的所有分钟
  •   
  • t_seconds :匹配从0059的任何秒数
  •   
  • t_milliseconds :匹配任意3位数(000999
  •   
  • t_format :这指向以前的群组,以确保时间格式正确。我添加了额外的时间设置(如   以及其他人的加法,包括毫秒和时间段。   使用)
  •   
  • dt_format :要检查的日期时间格式(在您的情况下,date time - 按空格字符分隔)
  •   
  • 定义块后面是\b(?&dt_format)\b,它只是匹配上面指定的dt_format,确保前面和后面的内容   取代它是一个单词边界字符(或没有字符)\b
  •   
     

闰年

     

进一步了解正则表达式的闰年部分......

     

我假设以下内容:

     
      
  • 所有年份闰年,除非以下情况属实      
        
    • ((年份模40 AND (年模100不是0))(年模4000
    •   
    • 来源:leap year calculation
    •   
    • 闰年一直存在(至少从第1年开始) - 因为我不想开始假设并做更多的研究。
    •   
  •   
     

正则表达式通过确保:

起作用      
      
  1. 0, 4, 8结尾的所有闰年先于 0, 2, 4, 6, 8(所有这些在模数后都会导致0 - &gt;即{{1 }})
  2.   
  3. 24 % 4 = 0结尾的所有闰年都在**前面2, 6(所有这些都在1, 3, 5, 7, 9之后产生模数 - &gt;即0)< / LI>   
  4. 32 % 4 = 0结尾的所有闰年,以及为1和2。的所有闰年均被否定(00执行此操作)
  5.   
  6. (?!00)结尾的所有闰年之后 。和2. (自00以来完全一样 - 没有什么需要改变的   除最后两位数外)
  7.   
  8. 添加年份4 * 100 = 400,因为他们不满足上述任何条件
  9.   

答案 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)))

工作示例:https://regex101.com/r/mjfoAH/3