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


143

我有一个python方法,它接受日期输入作为字符串

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

'YYYY-MM-DD'

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


2
根本不检查并捕获任何发生的异常可能是更Pythonic的(请谅解,而不是允许)。
托马斯

Answers:


230
>>> 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

8
有没有没有尝试/例外的方法吗?当引发并捕获异常时,Python往往会显着降低速度。
chiffa'9

1
@chiffa您可以匹配日期格式的正则表达式,但不建议使用它,因为它不那么健壮,并且异常更清晰。您确定日期验证是您的瓶颈吗?
jamylak

1
并非如此,因此最后我将把throw-except构造包装在一个函数中。令我惊讶的是,在日期时间库中没有可以触发异常抛出的布尔返回值验证函数。
chiffa

@chiffa也许他们没有故意包含bool返回验证函数,它可能存在于外部库中
jamylak 16/09/13

2
对于那些希望在日期中使用零填充的用户,此解决方案将不起作用,因为strptime对于零填充并不严格。实现自己的正则表达式,或在去除空格后检查结果字符串的长度,然后使用此解决方案。
Suparshva '18

65

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

1
它可能接受太多,例如,parse('13/12/2001')是“ 12月13日”,但是parse('11/12/2001')“ 11月12日”(第一个结果表示此处为“ 12月11日”)。
jfs 2015年

2
parse实际上需要一个dayfirst关键字参数,您可以控制它。 parse('11/12/2001', dayfirst=True)将返回“ 12月11日”。dateutil的默认值为dayfirst=False
Jacinda

您错过了datetutil.parser.parse()接受太多时间格式的问题(您可能会发现其他示例的输入含糊)。如果要验证您的输入为YYYY-MM-DD格式,则该parse()功能是错误的工具。
jfs 2015年

1
这是完全正确的一点-如果您真的想限制为特定格式,则不会这样做,并且在这种情况下,可以接受的答案已经做好了正确的事情。我想当我写答案时,我在思考如何验证日期是否是有效日期,而不是作者要求的特定格式,这是人们经常遇到的问题。寻找。
Jacinda

.parse()除了datetime对象之外,还有什么方法可以返回格式字符串?
citynorman

35

我认为完整的验证功能应如下所示:

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')

将被执行而没有错误。


3
“您在技术上是正确的-最好的正确选择。” 我需要在字符串中确保这一点。
delrocco

这在我的测试中可以正常工作,但是我的文档似乎不正确,因为它指出:“%d->月份中的天,以零填充的十进制数字-> 01、02,...,31”,对于%m相同->以零填充的十进制数字表示月份。-> 01,02,…,12docs.python.org
library/

如果您需要检查月份和日期是否为零填充,仅检查字符串的长度和就不够datetime.strptime(date_text, "%Y-%m-%d")吗?
凯尔·巴伦

17
from datetime import datetime

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

ValueError..如果收到不兼容的格式,则会引发a 。

..如果您要处理大量的日期和时间(就日期时间对象而言,而不是unix时间戳浮动),那么最好查看pytz模块,对于storage / db,将所有内容存储在UTC中。


2
您速度更快,我本人会自己发布( ideone.com/vuxDDf)。赞成。
塔德克2013年

..刚发布后就看到了它,并且碰巧今天一直在使用日期时间对象。
B先生

-7

这是最简单的方法:

date = datetime.now()
date = date.strftime('%Y-%m-%d_%H-%M-%S.jpg')

2
最好有一个解释,而不仅仅是代码。
lukas_o
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.