我需要将RFC 3339字符串(如“2008-09-03T20:56:55.450686Z”)解析为Python的datetime类型。
我在Python标准库中找到了strptime,但它不是很方便。
最好的方法是什么?
我需要将RFC 3339字符串(如“2008-09-03T20:56:55.450686Z”)解析为Python的datetime类型。
我在Python标准库中找到了strptime,但它不是很方便。
最好的方法是什么?
当前回答
Python>=3.11
fromsoformat现在直接解析Z:
from datetime import datetime
s = "2008-09-03T20:56:35.450686Z"
datetime.fromisoformat(s)
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=datetime.timezone.utc)
Python 3.7到3.10
一个注释中的简单选项:将“Z”替换为“+00:00”-并使用fromsoformat:
from datetime import datetime
s = "2008-09-03T20:56:35.450686Z"
datetime.fromisoformat(s.replace('Z', '+00:00'))
# datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=datetime.timezone.utc)
为什么更喜欢来自同一格式?
虽然strptime的%z可以将“z”字符解析为UTC,但fromsoformat的速度要快~x40(另请参阅:更快的strptime):
%timeit datetime.fromisoformat(s.replace('Z', '+00:00'))
388 ns ± 48.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit dateutil.parser.isoparse(s)
11 µs ± 1.05 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f%z')
15.8 µs ± 1.32 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit dateutil.parser.parse(s)
87.8 µs ± 8.54 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
(Windows 10上的Python 3.9.12 x64)
其他回答
如果您使用的是Django,它提供了日期解析模块,它接受一系列类似于ISO格式的格式,包括时区。
如果您没有使用Django,并且不想使用这里提到的其他库之一,那么您可能会将Django的dateparse源代码调整为适合您的项目。
我是iso8601utils的作者。它可以在GitHub或PyPI上找到。下面是如何解析示例:
>>> from iso8601utils import parsers
>>> parsers.datetime('2008-09-03T20:56:35.450686Z')
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
如果不想使用dateutil,可以尝试使用以下函数:
def from_utc(utcTime,fmt="%Y-%m-%dT%H:%M:%S.%fZ"):
"""
Convert UTC time string to time.struct_time
"""
# change datetime.datetime to time, return time.struct_time type
return datetime.datetime.strptime(utcTime, fmt)
测试:
from_utc("2007-03-04T21:08:12.123Z")
结果:
datetime.datetime(2007, 3, 4, 21, 8, 12, 123000)
现在有玛雅:人类的日期时间™, 来自流行的Requests:HTTP for Humans的作者™ 包裹:
>>> import maya
>>> str = '2008-09-03T20:56:35.450686Z'
>>> maya.MayaDT.from_rfc3339(str).datetime()
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=<UTC>)
def parseISO8601DateTime(datetimeStr):
import time
from datetime import datetime, timedelta
def log_date_string(when):
gmt = time.gmtime(when)
if time.daylight and gmt[8]:
tz = time.altzone
else:
tz = time.timezone
if tz > 0:
neg = 1
else:
neg = 0
tz = -tz
h, rem = divmod(tz, 3600)
m, rem = divmod(rem, 60)
if neg:
offset = '-%02d%02d' % (h, m)
else:
offset = '+%02d%02d' % (h, m)
return time.strftime('%d/%b/%Y:%H:%M:%S ', gmt) + offset
dt = datetime.strptime(datetimeStr, '%Y-%m-%dT%H:%M:%S.%fZ')
timestamp = dt.timestamp()
return dt + timedelta(hours=dt.hour-time.gmtime(timestamp).tm_hour)
注意,如果字符串不以Z结尾,我们可以使用%Z进行解析。