Ruby 正则表达式匹配日期

Ruby 正则表达式匹配日期,ruby,regex,Ruby,Regex,我想用mm/dd/yy或mm/dd/yyy格式匹配日期,但它不应该选择2010年9月23日,其中月23无效,也不应该选择一些无效日期,如2020年12月00日或2011年12月12日。您最好对所有单个部件进行拆分/测试。但是如果你真的想使用正则表达式,你可以试试这个: #\A(?:(?:(?:(?:0?[13578])|(1[02]))/31/(19|20)?\d\d)|(?:(?:(?:0?[13-9])|(?:1[0-2]))/(?:29|30)/(?:19|20)?\d\d)|(?:0?2

我想用mm/dd/yy或mm/dd/yyy格式匹配日期,但它不应该选择2010年9月23日,其中月23无效,也不应该选择一些无效日期,如2020年12月00日或2011年12月12日。

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

#\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
我已经解释了第一部分,剩下的作为练习


此匹配一个无效日期:1900年2月29日,但对于1900年1月1日至2099年12月31日之间的任何其他日期都是正确的。使用regexp时,最好验证格式,例如:

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

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

或者您只需使用
date.parse“some random date”

如果ArgumentException解析失败(=>Date无效),您将获得ArgumentException


例如,请参见比疯狂的大型正则表达式更好的方法(假设这是为了验证而不是扫描):


还有一篇社论:哎哟!你为什么要使用如此糟糕的日期格式?对于ISO8601,
YYYY-MM-DD
,它是一个有效的国际标准,具有一致的零件顺序,并且按字典顺序进行排序。

对于
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))))

签出匹配在

中,因此您需要匹配为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,并且不会验证您可以测试正则表达式的任何假日期
您可以测试日期为2040年12月30日和2020年9月9日,以及您想要的格式。我认为这也是您可以找到的该格式最短的正则表达式。以下是您可以使用的代码:),请尝试并告诉我:



^([0-2][0-9]|(3)[0-1])(\/)((0)[0-9])|((1)[0-2])(\/)\d{4}$
+1用于建议拆分。这是使用这些规格的最简单方法。@egarcia:谢谢。当然,它当然更好,也更具可读性。如果要锚定正则表达式进行单字符串验证,那么应该使用
\A
\z
而不是
^
$
@Phrogz:这取决于正则表达式的风格。但是,你对Ruby是正确的。如果用户根本不输入斜杠怎么办?拆分方法不起作用。正如其他答案所示,这根本不是真的。尽管正则表达式变得丑陋和笨拙,但您可以将有效性与任意级别的正确性相匹配。@Phrogz。这几乎是真的。被接受的答案是错误的,因为M42通知;它不能正确处理闰年。为了做到这一点,它必须包含有关切换到Gregorian等的信息。那么,正则表达式将是一团混乱。我显然有偏见,但+1 sawa.。-)这不是一项容易的任务(尽管可能)。要做到这一点,您必须在正则表达式中处理闰年。@sawa和非闰世纪,除了%400闰世纪之外。+1表示所有建议。正则表达式非常适合抓取部件,但在验证范围方面却很糟糕。而且,是的,ISO8601格式可以治愈很多疾病。我在早些时候读过这篇文章,并不真正理解为什么字典排序是一件好事。它允许您对日期进行排序或使用字符串比较查找最低/最高日期!e、 g
'2014-01-01>'2013-12-12'=true
。使用
mm/dd/yy
或任何类似的方法都会失败。对不起,正如对@Simon Woker所说的那样,向reg exp提出的问题不是验证日期的通用解决方案,因此,对我来说-1@Filippo1980谢谢你的解释。这是否决投票的合理理由。这很漂亮,谢谢你用regex手术刀为我节省了很多时间。如果你有未经验证的字符串,请小心。例如,使用邮政编码会产生不期望的结果
DateTime.parse('60201-4286')。to__
给出了
“2060-07-19T00:00:00+00:00”
,并且没有失败。@Simon Woker:我对你的答案投-1票,因为这个问题要求一个正则表达式,而不是验证日期的解决方案,所以,很抱歉,对我来说,这可能是一个好的答案
DateTime.parse('Oxio'))
`=>#`在这件事上我们必须信任你吗?或者你能解释一下这个正则表达式的作用吗?你可以继续相信我。:)首先,它确保您不能在9月、4月、6月和11月添加“31”。2月29日只能用于闰年,只要闰年在1900-2099之间,它就可以工作。请让我知道这是否有用。你试过了吗?它匹配
00/00/0000
,不确定它是有效日期!它还与
2000年2月31日
2018年6月31日
匹配,但与
2018年6月6日
不匹配。此外,OP希望日期格式为
mm/dd/yy
mm/dd/yyyy
^((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}$