在"时间数据与格式不匹配的情况下捕获无效的月/日"

时间:2016-01-08 16:52:08

标签: python datetime

我使用以下内容转换日期字符串(不是完整代码,只是相关位):

str_format = '%Y-%m-%d %H:%M:%S'
datetime.strptime('2015-13-23 13:43:23', str_format)

这会导致"时间数据与格式不匹配"因为月份错了(13不是有效月份)。

我想知道是否有可能在月份(或日期)因无效日期而无法匹配的格式引发异常?以下清楚地表明日期时间可以确定:

>>> print datetime(2015, 13, 23)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: month must be in 1..12

2 个答案:

答案 0 :(得分:1)

您可以随时解析文本,然后自己使用它来构建日期时间 - 或者如果适合您,则预先验证它:

from datetime import datetime

def to_datetime(date_string):
    year = int(date_string[0:4])
    month = int(date_string[5:7])
    day = int(date_string[8:10])

    return datetime(year, month, day)

print(to_datetime('2015-13-23 13:42:13'))

抛出:

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    print(to_datetime('2015-13-23 13:42:13'))
  File "test.py", line 9, in to_datetime
    return datetime(year, month, day)
ValueError: month must be in 1..12

如果你想知道datetime是如何做到的 - 请使用Source,Luke!

>>> import datetime
>>> datetime.__file__
'/usr/lib/python3.5/datetime.py'

打开该文件,你会发现:

def _check_date_fields(year, month, day):
    year = _check_int_field(year)
    month = _check_int_field(month)
    day = _check_int_field(day)
    if not MINYEAR <= year <= MAXYEAR:
        raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
    if not 1 <= month <= 12:
        raise ValueError('month must be in 1..12', month)
    dim = _days_in_month(year, month)
    if not 1 <= day <= dim:
        raise ValueError('day must be in 1..%d' % dim, day)
    return year, month, day

答案 1 :(得分:0)

我觉得有两种方法可以解决这个问题:

方式1

str_format = '%Y-%m-%d %H:%M:%S'

try:
    datetime.strptime('2015-13-23 13:43:23', str_format)
except ValueError:
    raise ValueError("Something went wrong")

这方面的缺点是,它不仅限于情况,其中月份或日期错误,正如您最初提出的问题。

方式2

import calendar

str_format = '%Y-%m-%d %H:%M:%S'
datetime_str = '2015-13-23 13:43:23'
year = int(datetime_str[0:4])
month = int(datetime_str[5:7])
day = int(datetime_str[8:10])
cal = calendar.Calendar(6)

if not 1 <= month <= 12:
    raise ValueError("wrong month")
else:
    days_list = list(cal.itermonthdays(year, month))
    if day not in days_list:
        raise ValueError("invalid day")

如果您想使用生成器而不转换为列表

....

if not 1 <= month <= 12:
    raise ValueError("wrong month")

days_gen = cal.itermonthdays(year, month)

for gen_day in days_gen:
    if gen_day == day:
        break
else:
    raise ValueError("wrong day")