在“时间数据与格式不匹配”​​中捕获无效的月/日

Posted

技术标签:

【中文标题】在“时间数据与格式不匹配”​​中捕获无效的月/日【英文标题】:Catch invalid month/day in "time data does not match format" 【发布时间】:2016-04-13 10:27:46 【问题描述】:

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

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

这会抛出“时间数据与格式不匹配”​​,因为月份错误(13 不是有效月份)。

我想知道是否有可能让它在月份(或日期)无效时引发异常而不是由于日期无效而导致格式不匹配?下面清楚地表明 datetime 可以确定:

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

【问题讨论】:

最常见的获取错误的方法是交换月份和日期,因为美国和欧洲的习惯是相反的,所以错误是有道理的。 你为什么会在第 13 个月过世? 不确定这是否是正确的方法,但可能你可以从异常块中引发异常 @NotAnAmbiTurner 我认为这就是重点——也许有人指手画脚,或者正如 Mark 指出的那样,他们习惯了不同的格式并输入类似2015-13-08 @NotAnAmbiTurner,韦恩说得对,我正在尝试处理有人输入无效月/日(例如第 13 个月)的情况,并提醒他们注意这一点,而不是“不匹配格式”。字符串 does 匹配格式,只是月份是错误的,它最终给出的异常并不清楚。 【参考方案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 是如何做到的 - 请使用源代码,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

【讨论】:

日切片应该是date_string[8:10] @NotAnAmbiTurner 啊,你是对的。显然int 忽略尾随空格:) @WayneWerner:这比我预期的要多(一点),但这肯定涵盖了它!我试图查找 datetime.py 文件,但 apparently 我必须去获取一个 tarball 才能在 Windows 上找到它:-/ 哦,有趣。你也可以去GitHub找到源代码【参考方案2】:

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

方式 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")

【讨论】:

最好指定Exception Type,而不是监视所有异常

以上是关于在“时间数据与格式不匹配”​​中捕获无效的月/日的主要内容,如果未能解决你的问题,请参考以下文章

document.getElementById 错误:未捕获的 ReferenceError:分配中的左侧无效

仅在案例语句中添加年份得到无效数字错误 - ORA-01722

iOS 8:从 NSFetchedResultsController 的委托中捕获异常,无效更新:第 0 节中的行数无效

未捕获的 ReferenceError:分配中的左侧无效

我将XML发送到无效URL时如何捕获错误? (蟒蛇)

未捕获的错误:不变违规:元素类型无效:对象