【问题标题】:Regex to match Date正则表达式匹配日期
【发布时间】:2011-08-24 03:00:09
【问题描述】:

我想匹配格式为 mm/dd/yy 或 mm/dd/yyyy 的日期,但它不应该选择 23/09/2010,其中月份为 23 是无效的,也不能选择像 00/12/2020 或 12 这样的无效日期/00/2011.

【问题讨论】:

  • 这不是一件容易的事(尽管它可能是可能的)。您必须在正则表达式中处理闰年才能做到这一点。
  • @sawa 和非闰世纪,除了 % 400 闰世纪。

标签: ruby regex


【解决方案1】:

比一个疯狂的大正则表达式更好(假设这是用于验证而不是扫描):

require 'date'
def valid_date?( str, format="%m/%d/%Y" )
  Date.strptime(str,format) rescue false
end

除了社论之外:Eww!你为什么要使用如此糟糕的日期格式?选择 ISO8601,YYYY-MM-DD,这是一个有效的国际标准,具有一致的部件顺序,并且按字典顺序排序。

【讨论】:

  • +1 表示所有推荐。正则表达式非常适合抓取零件,但用于验证范围很糟糕。而且,是的,ISO8601 格式可以治愈很多弊病。
  • 我之前读过这篇文章,并没有真正理解为什么按字典顺序排序是一件好事。它允许您使用字符串比较对日期进行排序或查找最低/最高日期!例如'2014-01-01 > '2013-12-12' = true。使用mm/dd/yy 或类似的东西会失败。
  • 很抱歉,但正如告诉@Simon-Woker 的那样,向 reg exp 提出的问题不是验证日期的通用解决方案,所以对我来说是 -1
  • @Filippo1980 感谢您的解释。投反对票是一个合理的理由。
【解决方案2】:

您最好对 / 进行拆分并测试所有单独的部分。但如果你真的想使用正则表达式,你可以试试这个:

#\A(?:(?:(?:(?:0?[13578])|(1[02]))/31/(19|20)?\d\d)|(?:(?:(?:0?[13-9])|(?:1[0-2]))/(?:29|30)/(?:19|20)?\d\d)|(?:0?2/29/(?:19|20)(?:(?:[02468][048])|(?:[13579][26])))|(?:(?:(?:0?[1-9])|(?:1[0-2]))/(?:(?:0?[1-9])|(?:1\d)|(?:2[0-8]))/(?:19|20)?\d\d))\Z#

解释:

\A           # start of string
 (?:         # group without capture
             # that match 31st of month 1,3,5,7,8,10,12
   (?:       # group without capture
     (?:     # group without capture
       (?:   # group without capture
         0?  # number 0 optionnal
         [13578] # one digit either 1,3,5,7 or 8
       )     # end group
       |     # alternative
       (1[02]) # 1 followed by 0 or 2
     )       # end group
     /       # slash
     31      # number 31
     /       # slash
     (19|20)? #numbers 19 or 20 optionnal
     \d\d    # 2 digits from 00 to 99 
   )         # end group
|
   (?:(?:(?:0?[13-9])|(?:1[0-2]))/(?:29|30)/(?:19|20)?\d\d)
|
   (?:0?2/29/(?:19|20)(?:(?:[02468][048])|(?:[13579][26])))
|
   (?:(?:(?:0?[1-9])|(?:1[0-2]))/(?:(?:0?[1-9])|(?:1\d)|(?:2[0-8]))/(?:19|20)?\d\d)
 )
\Z

我已经解释了第一部分,剩下的留作练习。

这匹配一个无效日期:02/29/1900,但对于 01/01/1900 和 12/31/2099 之间的任何其他日期都是正确的

【讨论】:

  • +1 推荐拆分。这是符合这些规范的最简单方法。
  • @egarcia:谢谢。当然它肯定更好,也更具可读性。
  • 如果您要锚定正则表达式进行单字符串验证,那么您应该使用\A\z 而不是^$
  • @Phrogz:这取决于正则表达式的风格。但是,你适合 Ruby。
  • 如果用户根本不输入斜线怎么办? split 方法不起作用。
【解决方案3】:

或者您只需使用Date.parse "some random date"
如果解析失败(=> 日期无效),您将收到 ArgumentException。

参见例如http://santoro.tk/mirror/ruby-core/classes/Date.html#M000644

【讨论】:

  • 这很漂亮,谢谢你用正则表达式手术刀为我节省了很多时间。
  • 如果您有未经验证的字符串,请小心。例如,使用邮政编码会产生不希望的结果。 DateTime.parse('60201-4286').to_s 给出"2060-07-19T00:00:00+00:00" 并且不会失败。
  • @Simon-Woker :我对您的回答投了-1票,因为该问题询问的是正则表达式,而不是验证日期的解决方案所以,对不起,但对我来说,这可能是一个很好的答案
  • DateTime.parse('monoxide') ` => # `
【解决方案4】:

您可以使用正则表达式做的最好的事情是验证格式,例如类似:

[0-1][0-9]/[0-3][0-9]/[0-9]{2}(?:[0-9]{2})?

如果没有某种日期字典,除此之外的任何事情都无法可靠地完成。例如,日期的有效性取决于它是否是闰年。

【讨论】:

  • 如其他答案所示,这根本不是真的。尽管正则表达式变得丑陋且笨拙,但您可以将有效性与任意程度的正确性相匹配。
  • @Phrogz。这实际上是真的。 M42 注意到,接受的答案是错误的;它不能正确处理闰年。为了做到这一点,它必须包含有关切换到公历等的信息。那么,正则表达式将是一团糟。
  • 我显然有偏见,但 +1 sawa。 ;-)
【解决方案5】:

对于MM-DD-YYYY,您可以使用以下正则表达式。它适用于闰年,并且仅匹配正确的日期,除非年份不超过 2099 年。

(?:(09|04|06|11)(\/|-|\.)(0[1-9]|[12]\d|30)(\/|-|\.)((?:19|20)\d\d))|(?:(01|03|05|07|08|10|12)(\/|-|\.)(0[1-9]|[12]\d|3[01])(\/|-|\.)((?:19|20)\d\d))|(?:02(\/|-|\.)(?:(?:(0[1-9]|1\d|2[0-8])(\/|-|\.)((?:19|20)\d\d))|(?:(29)(\/|-|\.)((?:(?:19|20)(?:04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))|2000))))

结帐匹配 http://regexr.com/

【讨论】:

  • 我们是否必须信任你,或者你能解释一下这个正则表达式的作用吗?
  • 你可以继续相信我。 :) 对于初学者,它确保您不能为 9 月、4 月、6 月和 11 月添加“31”。只能为闰年添加 2 月 29 日,只要年份在 1900 年至 2099 年之间,它就可以工作。如果这有帮助,请告诉我。
【解决方案6】:

所以你想要一个匹配为 mm/dd/yy 的正则表达式

^((0?1?1){1}|(0?1?2){1}|([0]?3|4|5|6|7|8|9))\/((0?1?2?3?1){1}|(0?1?2?(2|3|4|5|6|7|8|9|0))|(30))\/[1-90]{4}$

此正则表达式将完全匹配您想要的格式 mm/dd/yy 并且不会验证您可以在 regex101 上测试正则表达式的任何假日期 你可以测试日期 12/30/2040 和 09/09/2020 以及你想要的那种格式,我认为这也是你能找到的最短的正则表达式

【讨论】:

    【解决方案7】:

    这是你可以使用的代码:),试试看告诉我:

    ^([0-2][0-9]|(3)[0-1])(\/)(((0)[0-9])|((1)[0-2]))(\/)\d{4}$

    【讨论】:

    • 你试过了吗?它与00/00/0000 匹配,不确定日期是否有效!它还匹配31/02/200031/06/2018,但不匹配06/06/18。此外,OP希望日期格式为mm/dd/yymm/dd/yyyy
    猜你喜欢
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 2011-12-17
    • 1970-01-01
    相关资源
    最近更新 更多