如何在python中验证日期字符串格式?

我有一个接受以字符串形式输入的日期的python方法。

我如何添加一个验证,以确保传递给方法的日期字符串是在ffg。格式:

'YYYY-MM-DD'

如果不是,方法应该引发某种错误

343982 次浏览

Python dateutil库就是为此而设计的(以及更多)。它会自动为你将其转换为datetime对象,如果不能,则抛出ValueError

举个例子:

>>> from dateutil.parser import parse
>>> parse("2003-09-25")
datetime.datetime(2003, 9, 25, 0, 0)

如果日期格式不正确,将引发ValueError:

>>> parse("2003-09-251")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 720, in parse
return DEFAULTPARSER.parse(timestr, **kwargs)
File "/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 317, in parse
ret = default.replace(**repl)
ValueError: day is out of range for month

如果你将来开始需要解析其他格式,dateutil也非常有用,因为它可以智能地处理大多数已知的格式,并允许你修改你的规范:dateutil解析示例

如果需要的话,它还可以处理时区。

根据评论进行更新: parse还接受关键字参数dayfirst,该参数控制在日期不明确的情况下,日期是先到还是先到。默认为False。如。

>>> parse('11/12/2001')
>>> datetime.datetime(2001, 11, 12, 0, 0) # Nov 12
>>> parse('11/12/2001', dayfirst=True)
>>> datetime.datetime(2001, 12, 11, 0, 0) # Dec 11
from datetime import datetime


datetime.strptime(date_string, "%Y-%m-%d")

..如果它接收到不兼容的格式,将引发ValueError

..如果你要处理大量的日期和时间(在datetime对象的意义上,而不是unix时间戳浮动),最好研究一下pytz模块,对于storage/db,将所有内容都存储为UTC。

>>> import datetime
>>> def validate(date_text):
try:
datetime.datetime.strptime(date_text, '%Y-%m-%d')
except ValueError:
raise ValueError("Incorrect data format, should be YYYY-MM-DD")


    

>>> validate('2003-12-23')
>>> validate('2003-12-32')


Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
validate('2003-12-32')
File "<pyshell#18>", line 5, in validate
raise ValueError("Incorrect data format, should be YYYY-MM-DD")
ValueError: Incorrect data format, should be YYYY-MM-DD

我认为完整的验证函数应该是这样的:

from datetime import datetime


def validate(date_text):
try:
if date_text != datetime.strptime(date_text, "%Y-%m-%d").strftime('%Y-%m-%d'):
raise ValueError
return True
except ValueError:
return False

执行的是

datetime.strptime(date_text, "%Y-%m-%d")

是不够的,因为strptime方法不检查月份和月份中的日期是否是零填充的十进制数。例如

datetime.strptime("2016-5-3", '%Y-%m-%d')

将被正确执行。

出于好奇,我计算了上面两个相互矛盾的答案。
结果如下:

dateutil.parser (valid str): 4.6732222699938575
dateutil.parser (invalid str): 1.7270505399937974
datetime.strptime (valid): 0.7822393209935399
datetime.strptime (invalid): 0.4394566189876059

下面是我使用的代码(Python 3.6)


from dateutil import parser as date_parser
from datetime import datetime
from timeit import timeit




def is_date_parsing(date_str):
try:
return bool(date_parser.parse(date_str))
except ValueError:
return False




def is_date_matching(date_str):
try:
return bool(datetime.strptime(date_str, '%Y-%m-%d'))
except ValueError:
return False






if __name__ == '__main__':
print("dateutil.parser (valid date):", end=' ')
print(timeit("is_date_parsing('2021-01-26')",
setup="from __main__ import is_date_parsing",
number=100000))


print("dateutil.parser (invalid date):", end=' ')
print(timeit("is_date_parsing('meh')",
setup="from __main__ import is_date_parsing",
number=100000))


print("datetime.strptime (valid date):", end=' ')
print(timeit("is_date_matching('2021-01-26')",
setup="from __main__ import is_date_matching",
number=100000))


print("datetime.strptime (invalid date):", end=' ')
print(timeit("is_date_matching('meh')",
setup="from __main__ import is_date_matching",
number=100000))