我需要将RFC 3339字符串(如“2008-09-03T20:56:55.450686Z”)解析为Python的datetime类型。
我在Python标准库中找到了strptime,但它不是很方便。
最好的方法是什么?
我需要将RFC 3339字符串(如“2008-09-03T20:56:55.450686Z”)解析为Python的datetime类型。
我在Python标准库中找到了strptime,但它不是很方便。
最好的方法是什么?
当前回答
要获得与2.X标准库兼容的功能,请尝试:
calendar.timegm(time.strptime(date.split(".")[0]+"UTC", "%Y-%m-%dT%H:%M:%S%Z"))
calendar.timegm是time.mktime缺少的gm版本。
其他回答
你得到的确切错误是什么?它像下面这样吗?
>>> datetime.datetime.strptime("2008-08-12T12:20:30.656234Z", "%Y-%m-%dT%H:%M:%S.Z")
ValueError: time data did not match format: data=2008-08-12T12:20:30.656234Z fmt=%Y-%m-%dT%H:%M:%S.Z
如果是,您可以将输入字符串拆分为“.”,然后将微秒添加到获得的日期时间中。
试试看:
>>> def gt(dt_str):
dt, _, us= dt_str.partition(".")
dt= datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S")
us= int(us.rstrip("Z"), 10)
return dt + datetime.timedelta(microseconds=us)
>>> gt("2008-08-12T12:20:30.656234Z")
datetime.datetime(2008, 8, 12, 12, 20, 30, 656234)
自Python 3.7以来,datetime标准库有一个用于反转datetime.isoformat()的函数。
classmethod datetime.fromisoformat(date_string):以任何有效的ISO 8601格式返回与date_string对应的日期时间,但以下情况除外:时区偏移可能有小数秒。T分隔符可以由任何单个unicode字符替换。当前不支持顺序日期。不支持分数小时和分钟。示例:>>>从datetime导入datetime>>>日期时间。来自同一格式(“2011-11-04”)datetime.datetime(2011,11,4,0,0)>>>datetime.fromisoformat('20111104')datetime.datetime(2011,11,4,0,0)>>>日期时间。来自同一格式('2011-11-04T00:05:23')datetime.datetime(2011,11,4,0,5,23)>>>日期时间。来自同一格式('2011-11-04T00:05:23Z')datetime.datetime(2011,11,4,0,5,23,tzinfo=datetime.timezone.utc)>>>日期时间。来自同一格式('20111104T000523')datetime.datetime(2011,11,4,0,5,23)>>>datetime.fromisoformat('2011-W01-2T0:05:32.283')datetime.datetime(2011,1,4,0,5,23,283000)>>>日期时间。来自同一格式('2011-11-04 00:05:23.283')datetime.datetime(2011,11,4,0,5,23,283000)>>>日期时间。来自同一格式('2011-11-04 00:05:23.283+00:00')datetime.datetime(2011,11,4,0,5,23,283000,tzinfo=datetime.timezone.utc)>>>日期时间。来自同一格式('2011-11-04T00:05:23+04:00')datetime.datetime(2011,11,4,0,5,23,tzinfo=datetime.timezone(datetime.time增量(秒=1440)))3.7版新增。3.11版本中更改:以前,此方法只支持date.isoformat()或datetime.isoformat()发出的格式。
如果您还没有升级到Python 3.11,请务必阅读文档中的警告!
python dateutil中的等参函数
python dateutil包具有dateutil.parser.isose,不仅可以解析RFC 3339日期时间字符串(如问题中的字符串),还可以解析其他不符合RFC 3339的ISO 8601日期和时间字符串(例如没有UTC偏移量的字符串,或仅表示日期的字符串)。
>>> import dateutil.parser
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686Z') # RFC 3339 format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686') # ISO 8601 extended format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903T205635.450686') # ISO 8601 basic format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903') # ISO 8601 basic format, date only
datetime.datetime(2008, 9, 3, 0, 0)
python dateutil包还具有dateutil.parser.parse。与isose相比,它可能不那么严格,但这两个函数都非常宽容,都会尝试解释传入的字符串。如果要消除任何误读的可能性,需要使用比这两个函式更严格的函数。
与Python 3.7+内置datetime.datetime.fromisoformat的比较
dateutil.parser.isorse是一个完整的ISO-8601格式解析器,但在Python≤3.10中,fromsoformat故意不是。在Python 3.11中,fromsoformat支持有效ISO 8601中的几乎所有字符串。请参阅isoformat的文档以了解此警告。(参见此答案)。
如果解析无效的日期字符串,python dateutil将抛出异常,因此您可能需要捕获该异常。
from dateutil import parser
ds = '2012-60-31'
try:
dt = parser.parse(ds)
except ValueError, e:
print '"%s" is an invalid date' % ds
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进行解析。