ValueError:“时间数据 %r 与格式 %r 不匹配”

ValueError: "time data %r does not match format %r"

提问人:Anthony 提问时间:11/11/2023 最后编辑:FObersteinerAnthony 更新时间:11/12/2023 访问量:67

问:

我正在尝试使用以下方法解析时间:strptime

t = datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z')

此代码在 GMT+4 中对我有用,但在 GMT-9 中失败:

ValueError: time data '2024-08-21T11:00:00 EDT' does not match format '%Y-%m-%dT%H:%M:%S %Z'

我做错了什么?

python 日期时间 时区 strptime

评论

0赞 LMC 11/11/2023
“它在 GMT-9 中失败”是什么意思?如果 python 在该 TZ 上运行,则失败?
1赞 OneCricketeer 11/11/2023
请显示它确实有效的字符串。另外,为什么标题有 %r,但这不是代码的一部分?
0赞 Anthony 11/11/2023
我使用相同的刺进行测试。唯一的区别是我更改了系统时区。
0赞 FObersteiner 11/12/2023
如果您有时不想依赖工作,您基本上必须定义缩写映射到哪个时区(“时区”是指 iana db 中的标识符)。使用 dateutil 的示例 - 但是,我不建议您为此需要 dateutil;编写应用此类映射的函数相对简单。%Z

答:

2赞 LMC 11/11/2023 #1

根据 python 文档,strptime() 只接受 %Z 的某些值

strptime() 只接受 %Z 的某些值: time.tzname 中计算机区域设置的任何值 硬编码值 UTC 和 GMT

因此,居住在日本的人可能将 JST、UTC 和 GMT 作为有效值,但可能不是 EST。它将为无效值引发 ValueError。

本地测试

TZ="+4" python3 -c "import time; print(time.tzname)"
TZ="+4" python3 -c "import datetime; print(datetime.datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z'))"

结果

('', '')
ValueError: unconverted data remains: EDT

对于受支持的 TZ

TZ="US/Eastern" python3 -c "import time; print(time.tzname)"
('EST', 'EDT')
TZ="US/Eastern" python3 -c "import datetime; print(datetime.datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z'))"
2024-08-21 11:00:00

甚至某些 TZ 的错误字符串也会发生变化。 返回 OP 报告的错误。America/Los_Angeles

 TZ="America/Los_Angeles" python3 -c "import datetime; print(datetime.datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z'))"

ValueError: time data '2024-08-21T11:00:00 EDT' does not match format '%Y-%m-%dT%H:%M:%S %Z'

即使 tzname 有值,仍然会失败

TZ="America/Los_Angeles" python3 -c "import time; print(time.tzname)"
('PST', 'PDT')

评论

1赞 FObersteiner 11/12/2023
这里需要注意的另一件重要事情是,即使“接受”时区名称缩写,它实际上也不会在生成的 datetime 对象中设置时区。对象仍然幼稚%Z
0赞 Marcin Orlowski 11/11/2023 #2

问题在于 Python 中的时区支持 () 依赖于底层 C 库,该库因不同系统而异,并且可能无法识别某些时区缩写,例如“EDT”。%Zstrptime()

您可以尝试通过单独处理 TZ 来解决这个问题。首先解析没有 TZ 部分的时间戳,然后手动调整结果。或者,使用 pytz 或其他库,它们可以拥有更广泛、更新的时区数据库。

from datetime import datetime, timedelta

def parse_datetime_with_tz(datetime_tz_str):
    # Split the input string into datetime and timezone parts
    datetime_str, tz_str = datetime_tz_str.rsplit(' ', 1)

    # Parse the datetime part
    dt = datetime.strptime(datetime_str, '%Y-%m-%dT%H:%M:%S')

    # TZ offests. Add more if needed 
    tz_offsets = {
        'EDT': -4,
    }

    tz_offset_hours = tz_offsets.get(tz_str, 0)
    tz_offset = timedelta(hours=tz_offset_hours)

    # Adjust the datetime for the timezone
    adjusted_dt = dt + tz_offset

    return adjusted_dt


timestamp = '2024-08-21T11:00:00 EDT'
parsed_dt = parse_datetime_with_tz(timestamp, timezone)
print(parsed_dt)