Python datetime.fromisoformat能否解析无冒号时区偏移的ISO时间?
如何用datetime.fromisoformat解析不带冒号的时区偏移ISO时间?
我需要解析其他应用生成的ISO格式时间,示例如下:
"2022-07-31T01:51:05-0400"
注意时区部分是-0400,不带冒号。
但直接用datetime.fromisoformat解析会报错:
# 带冒号的格式可以正常解析 datetime.fromisoformat("2022-07-31T01:51:05-04:00") # 输出:datetime.datetime(2022, 7, 31, 1, 51, 5, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000))) # 不带冒号的格式报错 datetime.fromisoformat("2022-07-31T01:51:05-0400") # 报错信息: # Traceback (most recent call last): # File "/usr/lib/python3.10/code.py", line 90, in runcode # exec(code, self.locals) # File "<input>", line 1, in <module> # ValueError: Invalid isoformat string: '2022-07-31T01:51:05-0400'
根据ISO 8601标准,UTC时间偏移允许三种格式:±[hh]:[mm]、±[hh][mm]或±[hh],-0400属于合法格式。而Python官方文档中,datetime.fromisoformat()的说明里,仅列出了几个不支持的ISO 8601子格式(序数日期、小数小时/分钟等),并不包含禁止不带冒号的时区偏移。
我知道可以用strptime显式指定格式来解析:
datetime.strptime("2022-07-31T01:51:05-0400", '%Y-%m-%dT%H:%M:%S%z')
但我不想手动查找并编写格式字符串,更希望继续使用fromisoformat的便捷性。
解决方案:预处理字符串后使用fromisoformat
可以先对时间字符串做简单预处理,给不带冒号的时区部分插入冒号,再调用fromisoformat解析。
方法1:字符串切片处理(适用于固定长度的时间格式)
import datetime def parse_iso_time(date_str): # 针对YYYY-MM-DDTHH:MM:SS±HHMM格式的字符串,插入时区冒号 if len(date_str) == 20 and date_str[-5] in ('+', '-') and date_str[-3] != ':': date_str = f"{date_str[:-2]}:{date_str[-2:]}" return datetime.datetime.fromisoformat(date_str) # 测试 dt = parse_iso_time("2022-07-31T01:51:05-0400") print(dt) # 输出:2022-07-31 01:51:05-04:00
方法2:正则表达式处理(兼容更多变体)
如果时间字符串可能有其他变体(比如缺少秒数),可以用正则匹配并替换时区部分:
import re import datetime def parse_iso_time(date_str): # 匹配结尾的±HHMM格式,替换为±HH:MM modified_str = re.sub(r'([+-])(\d{2})(\d{2})$', r'\1\2:\3', date_str) return datetime.datetime.fromisoformat(modified_str) # 测试多种格式 print(parse_iso_time("2022-07-31T01:51:05-0400")) print(parse_iso_time("2022-07-31T01:51+0800"))
这种方式既保留了fromisoformat无需指定完整格式的便捷性,又解决了不带冒号时区的解析问题。
内容的提问来源于stack exchange,提问作者philhanna
相关产品推荐
相关产品推荐

