使用python正则表达式进行日期匹配

时间:2012-04-10 10:25:04

标签: python regex

我在下面的正则表达式匹配

中做错了什么
>>> import re
>>> d="30-12-2001"
>>> re.findall(r"\b[1-31][/-:][1-12][/-:][1981-2011]\b",d)
[]

6 个答案:

答案 0 :(得分:6)

[1-31]匹配1-31,基本上是1,2或3.除非它是0-9的子集,否则无法匹配数字愤怒。同样适用于[1981-2011],它恰好匹配一个0,1,2,8或9的字符。

最好的解决方案是简单地匹配任何号码,然后使用python本身检查数字。诸如31-02-2012之类的日期没有任何意义 - 并且使您的正则表达式检查很难。使它也适当地处理闰年将使它更难或不可能。这是一个正则表达式匹配任何看起来像dd-mm-yyyy日期的内容:\b\d{1,2}[-/:]\d{1,2}[-/:]\d{4}\b

但是,我强烈建议不允许任何-:/作为:通常用于/通常用于美国为ISO方式(mm/dd/yyyy)编写日期(-)和yyyy-mm-dd的方式。欧盟dd.mm.yyyy语法根本没有处理。

如果字符串除日期外不包含任何内容,则根本不需要正则表达式 - 请改用strptime()

总而言之,告诉用户您期望的日期格式并解析该日期格式,拒绝其他任何内容。否则你会得到含糊不清的案例,例如04/05/2012(是5月5日还是4月?)。

答案 1 :(得分:1)

[1-31]并不代表您认为的含义。方括号语法匹配一系列字符,而不是一系列数字。可以使用正则表达式匹配一系列数字,但不实用。

如果您真的想为此使用正则表达式(而不是日期解析库),最好匹配正确数字位数的所有数字,捕获值,然后自己检查值:

>>> import re
>>> d="30-12-2001"
>>> >>> re.findall(r"\b([0-9]{1,2})[-/:]([0-9]{1,2})[-/:]([0-9]{4})\b",d)
[('30', '12', '2001')]

无论如何,您必须进行实际日期验证,以捕获31-02-2012之类的无效日期。

(注意[/-:]也不起作用,因为它被解释为一个范围。使用[-/:]代替 - 将连字符放在前面可防止它被解释为范围分隔符。)

答案 2 :(得分:1)

正则表达式不理解数字;对于正则表达式,1只是字符串的一个字符 - 与a相同。因此,例如,[1-31]被解析为包含范围1-3和(冗余)单个符号1的字符类。

您不希望使用正则表达式来解析日期。已有一个用于处理日期解析的内置模块:

>>> import datetime
>>> datetime.datetime.strptime('30-12-2001', '%d-%m-%Y')
datetime.datetime(2001, 12, 30, 0, 0) # an object representing the date.

这也会为您完成所有二次检查(例如尝试参考2月31日)。如果你想处理多种类型的分隔符,你只需在原始字符串中.replace它们,这样它们就会变成同一个分隔符,然后以你的格式使用它。

答案 3 :(得分:1)

你可能做错了。这里的一些其他回复正在帮助您使用正则表达式,但我建议您使用datetime.strptime方法将格式化日期转换为日期时间对象,并使用该对象执行进一步的逻辑:

>>> import datetime
>>> datetime.strptime('30-12-2001', '%d-%m-%Y')
datetime.datetime(2001, 12, 30, 0, 0)

More info on the strptime method and it's format strings.

答案 4 :(得分:1)

regexp = r'(0?[1-9] | [12] [0-9] | 3 [01])/(0?[1-9] | 1 [012])/((19 | 20)\ d \ d)'

(          #start of group #1
 0?[1-9]        #  01-09 or 1-9
 |                      #  ..or
 [12][0-9]      #  10-19 or 20-29
 |          #  ..or
 3[01]          #  30, 31
)           #end of group #1
  /         #  follow by a "/"
   (            #    start of group #2
    0?[1-9]     #   01-09 or 1-9
    |           #   ..or
    1[012]      #   10,11,12
    )           #    end of group #2
     /          #   follow by a "/"
      (         #     start of group #3
       (19|20)\\d\\d    #       19[0-9][0-9] or 20[0-9][0-9]
       )        #     end of group #3

答案 5 :(得分:0)

也许你可以试试这个正则表达式

^((0|1|2)[0-9]{1}|(3)[0-1]{1})/((0)[0-9]{1}|(1)[0-2]{1})/((19)[0-9]{2}|(20)[0-9]{2})$

此匹配为(01至31)/(01至12)/(1900至2099)