提问人:Alexander Artemenko 提问时间:9/24/2008 最后编辑:CommunityAlexander Artemenko 更新时间:10/16/2023 访问量:718425
如何解析 ISO 8601 格式的日期?
How do I parse an ISO 8601-formatted date?
问:
我需要将 RFC 3339 字符串解析为 Python 的类型。"2008-09-03T20:56:35.450686Z"
datetime
我在 Python 标准库中找到了 strptime
,但不是很方便。
最好的方法是什么?
答:
您得到的确切错误是什么?是不是像下面这样?
>>> 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)
评论
datetime.fromisoformat
import re
import datetime
s = "2008-09-03T20:56:35.450686Z"
d = datetime.datetime(*map(int, re.split(r'[^\d]', s)[:-1]))
评论
datetime.datetime(*map(int, re.findall('\d+', s))
尝试 iso8601 模块;它正是这样做的。
python.org wiki 的 WorkingWithTime 页面上还提到了其他几个选项。
评论
iso8601.parse_date("2008-09-03T20:56:35.450686Z")
注意:在 Python 2.6+ 和 Py3K 中,%f 字符捕获微秒。
>>> datetime.datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")
在此处查看问题
评论
datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f')
对于适用于 2.X 标准库的内容,请尝试:
calendar.timegm(time.strptime(date.split(".")[0]+"UTC", "%Y-%m-%dT%H:%M:%S%Z"))
calendar.timegm 是 time.mktime 缺少的 GM 版本。
评论
.
2022-10-09T15:49:22-07:00
我已经为 ISO 8601 标准编写了一个解析器,并将其放在 GitHub 上:https://github.com/boxed/iso8601。此实现支持规范中的所有内容,但持续时间、间隔、周期间隔和 Python 的 datetime 模块支持的日期范围之外的日期除外。
包括测试!:P
评论
isoparse
来自 python-dateutil 的函数
python-dateutil 包具有 dateutil.parser.isoparse
,不仅可以解析问题中的 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
。与 相比,它可能不那么严格,但它们都非常宽容,并且会尝试解释您传入的字符串。如果要消除任何误读的可能性,则需要使用比这些函数中的任何一个更严格的功能。isoparse
与 Python 3.7+ 内置的 datetime.datetime.fromisoformat
比较
dateutil.parser.isoparse
是一个完整的 ISO-8601 格式解析器,但在 Python ≤ 3.10 中故意不是。在 Python 3.11 中,支持有效 ISO 8601 中的几乎所有字符串。有关此警告,请参阅的文档。(请参阅此答案)。fromisoformat
fromisoformat
fromisoformat
评论
python-dateutil
dateutil
pip install python-dateutil
dateutil.parser
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
评论
如果你不想使用 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)
评论
strptime
toISOString
方法生成的,则可能是这种情况。但是这个答案中没有提到祖鲁时间日期的限制,问题也没有表明这就是所需要的,只是使用通常同样方便,而且可以解析的内容不那么狭窄。dateutil
如今,Arrow 还可以用作第三方解决方案:
>>> import arrow
>>> date = arrow.get("2008-09-03T20:56:35.450686Z")
>>> date.datetime
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
评论
这适用于 Python 3.2 及更高版本的 stdlib(假设所有时间戳都是 UTC):
from datetime import datetime, timezone, timedelta
datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%fZ").replace(
tzinfo=timezone(timedelta(0)))
例如
>>> datetime.utcnow().replace(tzinfo=timezone(timedelta(0)))
... datetime.datetime(2015, 3, 11, 6, 2, 47, 879129, tzinfo=datetime.timezone.utc)
评论
strptime
utc
tzinfo 对象,则代码在 Python 2.6+ 中(至少)有效timezone.utc
timezone(timedelta(0))
%Z
从 Python 3.7 开始,您基本上可以使用 datetime.datetime.strptime 解析 RFC 3339 日期时间,如下所示:
from datetime import datetime
def parse_rfc3339(datetime_str: str) -> datetime:
try:
return datetime.strptime(datetime_str, "%Y-%m-%dT%H:%M:%S.%f%z")
except ValueError:
# Perhaps the datetime has a whole number of seconds with no decimal
# point. In that case, this will work:
return datetime.strptime(datetime_str, "%Y-%m-%dT%H:%M:%S%z")
这有点尴尬,因为我们需要尝试两种不同的格式字符串,以便同时支持具有小数秒数的日期时间(如)和没有小数秒数的日期时间(如),这两者在 RFC 3339 下都有效。但只要我们做那一点点繁琐的逻辑,这就行得通。2022-01-01T12:12:12.123Z
2022-01-01T12:12:12Z
关于此方法需要注意的一些注意事项:
- 从技术上讲,它并不完全支持 RFC 3339,因为 RFC 3339 奇怪地允许您使用空格而不是 a 来分隔日期和时间,即使 RFC 3339 声称是 ISO 8601 的配置文件,而 ISO 8601 不允许这样做。如果你想支持RFC 3339的这个愚蠢的怪癖,你可以添加到函数的开头。
T
datetime_str = datetime_str.replace(' ', 'T')
- 我上面的实现比严格的 RFC 3339 解析器稍微宽松一些,因为它允许时区偏移量,例如没有冒号,而 RFC 3339 不支持。如果您不仅要解析已知的 RFC-3339 日期时间,还想严格验证您得到的日期时间是否为 RFC 3339,请使用其他方法或添加您自己的逻辑来验证时区偏移量格式。
+0500
- 此函数绝对不支持所有 ISO 8601,它包含的格式比 RFC 3339 广泛得多。(例如 是有效的 ISO 8601 日期。
2009-W01-1
- 它在 Python 3.6 或更早版本中不起作用,因为在那些旧版本中,说明符仅匹配时区偏移量,例如 or 或 ,而不是 RFC 3339 时区偏移量,例如 or 或 。
%z
+0500
-0430
+0000
+05:00
-04:30
Z
如果你正在使用 Django,它提供了 dateparse 模块,它接受一堆类似于 ISO 格式的格式,包括时区。
如果你不使用 Django,并且你不想使用这里提到的其他库之一,你可能会将 Django 源代码用于 dateparse 调整到你的项目中。
评论
DateTimeField
感谢伟大的 Mark Amery 的回答,我设计了函数来解释所有可能的 ISO 日期时间格式:
class FixedOffset(tzinfo):
"""Fixed offset in minutes: `time = utc_time + utc_offset`."""
def __init__(self, offset):
self.__offset = timedelta(minutes=offset)
hours, minutes = divmod(offset, 60)
#NOTE: the last part is to remind about deprecated POSIX GMT+h timezones
# that have the opposite sign in the name;
# the corresponding numeric value is not used e.g., no minutes
self.__name = '<%+03d%02d>%+d' % (hours, minutes, -hours)
def utcoffset(self, dt=None):
return self.__offset
def tzname(self, dt=None):
return self.__name
def dst(self, dt=None):
return timedelta(0)
def __repr__(self):
return 'FixedOffset(%d)' % (self.utcoffset().total_seconds() / 60)
def __getinitargs__(self):
return (self.__offset.total_seconds()/60,)
def parse_isoformat_datetime(isodatetime):
try:
return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S.%f')
except ValueError:
pass
try:
return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S')
except ValueError:
pass
pat = r'(.*?[+-]\d{2}):(\d{2})'
temp = re.sub(pat, r'\1\2', isodatetime)
naive_date_str = temp[:-5]
offset_str = temp[-5:]
naive_dt = datetime.strptime(naive_date_str, '%Y-%m-%dT%H:%M:%S.%f')
offset = int(offset_str[-4:-2])*60 + int(offset_str[-2:])
if offset_str[0] == "-":
offset = -offset
return naive_dt.replace(tzinfo=FixedOffset(offset))
因为 ISO 8601 允许存在许多可选冒号和破折号的变化,基本上.如果要使用 strptime,则需要先去除这些变体。
目标是生成一个 utc datetime 对象。CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
如果您只想要一个适用于 UTC 的基本情况,带有 Z 后缀,例如:
如果您想处理时区偏移量,例如或使用以下内容。这些会将所有变体转换为没有变量分隔符的内容,例如使其更一致/更易于解析。
如果您的系统不支持 strptime 指令(您会看到类似 )的内容,那么您需要手动偏移时间(UTC)。注意:在 python 版本 3 中<您的系统可能无法运行,因为它取决于 c 库支持,该支持因系统/python 构建类型(即 Jython、Cython 等)而异。
2016-06-29T19:36:29.3453Z
datetime.datetime.strptime(timestamp.translate(None, ':-'), "%Y%m%dT%H%M%S.%fZ")
2016-06-29T19:36:29.3453-0400
2008-09-03T20:56:35.450686+05:00
20080903T205635.450686+0500
import re
# this regex removes all colons and all
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)
datetime.datetime.strptime(conformed_timestamp, "%Y%m%dT%H%M%S.%f%z" )
%z
ValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z'
Z
%z
import re
import datetime
# this regex removes all colons and all
# dashes EXCEPT for the dash indicating + or - utc offset for the timezone
conformed_timestamp = re.sub(r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))", '', timestamp)
# split on the offset to remove it. use a capture group to keep the delimiter
split_timestamp = re.split(r"[+|-]",conformed_timestamp)
main_timestamp = split_timestamp[0]
if len(split_timestamp) == 3:
sign = split_timestamp[1]
offset = split_timestamp[2]
else:
sign = None
offset = None
# generate the datetime object without the offset at UTC time
output_datetime = datetime.datetime.strptime(main_timestamp +"Z", "%Y%m%dT%H%M%S.%fZ" )
if offset:
# create timedelta based on offset
offset_delta = datetime.timedelta(hours=int(sign+offset[:-2]), minutes=int(sign+offset[-2:]))
# offset datetime with timedelta
output_datetime = output_datetime + offset_delta
评论
timestamp
'2016-06-29T19:36:29.123Z'
'2016-06-29T19:36:29+00:00'
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
评论
在不安装第三方模块的情况下,在所有受支持的 Python 版本中将类似 ISO 8601 的日期字符串转换为 UNIX 时间戳或对象的一种直接方法是使用 SQLite 的日期解析器。datetime.datetime
#!/usr/bin/env python
from __future__ import with_statement, division, print_function
import sqlite3
import datetime
testtimes = [
"2016-08-25T16:01:26.123456Z",
"2016-08-25T16:01:29",
]
db = sqlite3.connect(":memory:")
c = db.cursor()
for timestring in testtimes:
c.execute("SELECT strftime('%s', ?)", (timestring,))
converted = c.fetchone()[0]
print("%s is %s after epoch" % (timestring, converted))
dt = datetime.datetime.fromtimestamp(int(converted))
print("datetime is %s" % dt)
输出:
2016-08-25T16:01:26.123456Z is 1472140886 after epoch
datetime is 2016-08-25 12:01:26
2016-08-25T16:01:29 is 1472140889 after epoch
datetime is 2016-08-25 12:01:29
评论
Django 的 parse_datetime()
函数支持带有 UTC 偏移量的日期:
parse_datetime('2016-08-09T15:12:03.65478Z') =
datetime.datetime(2016, 8, 9, 15, 12, 3, 654780, tzinfo=<UTC>)
因此,它可用于解析整个项目中字段中的 ISO 8601 日期:
from django.utils import formats
from django.forms.fields import DateTimeField
from django.utils.dateparse import parse_datetime
class DateTimeFieldFixed(DateTimeField):
def strptime(self, value, format):
if format == 'iso-8601':
return parse_datetime(value)
return super().strptime(value, format)
DateTimeField.strptime = DateTimeFieldFixed.strptime
formats.ISO_INPUT_FORMATS['DATETIME_INPUT_FORMATS'].insert(0, 'iso-8601')
我是iso8601utils的作者。它可以在 GitHub 或 PyPI 上找到。以下是分析示例的方法:
>>> from iso8601utils import parsers
>>> parsers.datetime('2008-09-03T20:56:35.450686Z')
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
只需使用以下模块:python-dateutil
>>> import dateutil.parser as dp
>>> t = '1984-06-02T19:05:00.000Z'
>>> parsed_t = dp.parse(t)
>>> print(parsed_t)
datetime.datetime(1984, 6, 2, 19, 5, tzinfo=tzutc())
评论
dateutil.parser.parse
将接受绝对不是 ISO 8601 的格式,例如 .如果你特别想要ISO 8601解析,你可能更愿意使用,正如Flimms的回答所建议的那样。"Sat Oct 11 17:13:46 UTC 2003"
dateutil.parse.isoparse
我发现 ciso8601 是解析 ISO 8601 时间戳的最快方法。
它还完全支持 RFC 3339,以及用于严格解析 RFC 3339 时间戳的专用函数。
用法示例:
>>> import ciso8601
>>> ciso8601.parse_datetime('2014-01-09T21')
datetime.datetime(2014, 1, 9, 21, 0)
>>> ciso8601.parse_datetime('2014-01-09T21:48:00.921000+05:30')
datetime.datetime(2014, 1, 9, 21, 48, 0, 921000, tzinfo=datetime.timezone(datetime.timedelta(seconds=19800)))
>>> ciso8601.parse_rfc3339('2014-01-09T21:48:00.921000+05:30')
datetime.datetime(2014, 1, 9, 21, 48, 0, 921000, tzinfo=datetime.timezone(datetime.timedelta(seconds=19800)))
GitHub Repo README 显示了它们与其他答案中列出的所有其他库相比的加速速度。
我个人的项目涉及大量的ISO 8601解析。能够切换呼叫并走得更快真是太好了。:)
编辑:从那以后,我成为了 ciso8601 的维护者。现在比以往任何时候都快!
评论
datetime.strptime()
datetime.strptime()
datetime.fromisoformat()
从 Python 3.7 开始,strptime 支持 UTC 偏移量中的冒号分隔符(来源)。因此,您可以使用:
import datetime
def parse_date_string(date_string: str) -> datetime.datetime
try:
return datetime.datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%S.%f%z')
except ValueError:
return datetime.datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%S%z')
编辑:
正如 Martijn 所指出的,如果您使用 isoformat() 创建了 datetime 对象,则只需使用 .datetime.fromisoformat()
编辑2:
正如马克·埃默里(Mark Amery)所指出的,我添加了一个尝试。除了块,以考虑丢失的小数秒。
评论
datetime.fromisoformat()
datetime.datetime.isoformat('2018-01-31T09:24:31.488670+00:00')
datetime.fromisoformat()
datetime.isoformat()
ValueError: time data '2018-01-31T09:24:31.488670+00:00' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
%z
+00:00
+0000
%z
fromisoformat()
Z
datetime.fromisoformat('2018-01-31T09:24:31Z')
datetime.datetime(2018, 1, 31, 9, 24, 31, tzinfo=datetime.timezone.utc)
从 Python 3.11 开始,标准库支持任何有效的 ISO 8601 输入。在早期版本中,它仅解析特定的子集,请参阅文档中的警告说明。如果您使用的是 Python 3.10 或更早版本,请参阅标准库外部函数的其他答案。文档:datetime.fromisoformat
类方法
DateTime.FromIsoFormat(date_string)
:以任何有效的 ISO 8601 格式返回与date_string相对应的 a,但以下情况除外:
datetime
- 时区偏移量可能具有小数秒。
- 分隔符可以替换为任何单个 unicode 字符。
T
- 目前不支持序号日期。
- 不支持小数小时和分钟。
例子:
>>> from datetime import datetime >>> datetime.fromisoformat('2011-11-04') datetime.datetime(2011, 11, 4, 0, 0) >>> datetime.fromisoformat('20111104') datetime.datetime(2011, 11, 4, 0, 0) >>> datetime.fromisoformat('2011-11-04T00:05:23') datetime.datetime(2011, 11, 4, 0, 5, 23) >>> datetime.fromisoformat('2011-11-04T00:05:23Z') datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc) >>> datetime.fromisoformat('20111104T000523') datetime.datetime(2011, 11, 4, 0, 5, 23) >>> datetime.fromisoformat('2011-W01-2T00:05:23.283') datetime.datetime(2011, 1, 4, 0, 5, 23, 283000) >>> datetime.fromisoformat('2011-11-04 00:05:23.283') datetime.datetime(2011, 11, 4, 0, 5, 23, 283000) >>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00') datetime.datetime(2011, 11, 4, 0, 5, 23, 283000, tzinfo=datetime.timezone.utc) >>> datetime.fromisoformat('2011-11-04T00:05:23+04:00') datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))
3.7 新版功能.
在 3.11 版更改:以前,此方法仅支持可由 date.isoformat() 或 datetime.isoformat() 发出的格式。
评论
datetime
tzinfo
datetime.fromisoformat()
isoformat
"2008-09-03T20:56:35.450686Z"
Z
"2008-09-03T20:56:35.450686"
Z
date_string.replace("Z", "+00:00")
datetime.fromisoformat
+00:00
+0000
现在有Maya: Datetimes for Humans,来自流行的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>)
最初我尝试了:
from operator import neg, pos
from time import strptime, mktime
from datetime import datetime, tzinfo, timedelta
class MyUTCOffsetTimezone(tzinfo):
@staticmethod
def with_offset(offset_no_signal, signal): # type: (str, str) -> MyUTCOffsetTimezone
return MyUTCOffsetTimezone((pos if signal == '+' else neg)(
(datetime.strptime(offset_no_signal, '%H:%M') - datetime(1900, 1, 1))
.total_seconds()))
def __init__(self, offset, name=None):
self.offset = timedelta(seconds=offset)
self.name = name or self.__class__.__name__
def utcoffset(self, dt):
return self.offset
def tzname(self, dt):
return self.name
def dst(self, dt):
return timedelta(0)
def to_datetime_tz(dt): # type: (str) -> datetime
fmt = '%Y-%m-%dT%H:%M:%S.%f'
if dt[-6] in frozenset(('+', '-')):
dt, sign, offset = strptime(dt[:-6], fmt), dt[-6], dt[-5:]
return datetime.fromtimestamp(mktime(dt),
tz=MyUTCOffsetTimezone.with_offset(offset, sign))
elif dt[-1] == 'Z':
return datetime.strptime(dt, fmt + 'Z')
return datetime.strptime(dt, fmt)
但这在负时区不起作用。但是我在 Python 3.7.3 中工作正常:
from datetime import datetime
def to_datetime_tz(dt): # type: (str) -> datetime
fmt = '%Y-%m-%dT%H:%M:%S.%f'
if dt[-6] in frozenset(('+', '-')):
return datetime.strptime(dt, fmt + '%z')
elif dt[-1] == 'Z':
return datetime.strptime(dt, fmt + 'Z')
return datetime.strptime(dt, fmt)
一些测试指出,输出仅因微秒精度而异。在我的机器上达到了 6 位数的精度,但 YMMV:
for dt_in, dt_out in (
('2019-03-11T08:00:00.000Z', '2019-03-11T08:00:00'),
('2019-03-11T08:00:00.000+11:00', '2019-03-11T08:00:00+11:00'),
('2019-03-11T08:00:00.000-11:00', '2019-03-11T08:00:00-11:00')
):
isoformat = to_datetime_tz(dt_in).isoformat()
assert isoformat == dt_out, '{} != {}'.format(isoformat, dt_out)
评论
frozenset(('+', '-'))
('+', '-')
to_datetime_tz
2019-03-11T08:00:00+11:00
Z
+00:00
frozenset
frozenset
另一种方法是为 ISO-8601 使用专用解析器,即使用 dateutil 解析器的 isoparse 函数:
from dateutil import parser
date = parser.isoparse("2008-09-03T20:56:35.450686+01:00")
print(date)
输出:
2008-09-03 20:56:35.450686+01:00
标准 Python 函数 datetime.fromisoformat 的文档中也提到了此函数:
一个功能更全面的 ISO 8601 解析器,dateutil.parser.isoparse 是 在第三方软件包 dateutil 中可用。
Python >= 3.11
fromisoformat
现在直接解析: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'
fromisoformat
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)
为什么更喜欢?fromisoformat
虽然 可以将字符解析为 UTC,但 fromisoformat
的速度要快 ~ x40(对于 Python 3.11 甚至更快 ~x60):strptime
%z
'Z'
from datetime import datetime
from dateutil import parser
s = "2008-09-03T20:56:35.450686Z"
# Python 3.11+
%timeit datetime.fromisoformat(s)
85.1 ns ± 0.473 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
# Python 3.7 to 3.10
%timeit datetime.fromisoformat(s.replace('Z', '+00:00'))
134 ns ± 0.522 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
%timeit parser.isoparse(s)
4.09 µs ± 5.2 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f%z')
5 µs ± 9.26 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit parser.parse(s)
28.5 µs ± 99.2 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
(GNU/Linux 上的 Python 3.11.3 x64)
Смотритетакже: 更快的 strptime
评论
fromisoformat
+00:00
Z
Z+00:00
Z
fromisoformat
+05:30
fromisoformat
datetime.date
如果无论如何都使用 pandas
,我可以推荐 Timestamp
。在那里你可以pandas
ts_1 = pd.Timestamp('2020-02-18T04:27:58.000Z')
ts_2 = pd.Timestamp('2020-02-18T04:27:58.000')
咆哮:令人难以置信的是,在2021年,我们仍然需要担心诸如日期字符串解析之类的事情。
评论
datetime.fromisoformat('2021-01-01T00:00:00+01:00').tzinfo.utc
pandas.Timestamp('2021-01-01T00:00:00+01:00').tzinfo.utc
datetime.fromisoformat()
在 Python 3.11 中进行了改进,可以解析大多数 ISO 8601 格式
datetime.fromisoformat() 现在可用于解析大多数 ISO 8601 格式,但仅支持小数小时和分钟格式除外。以前,此方法仅支持可由 datetime.isoformat() 发出的格式。
>>> from datetime import datetime
>>> datetime.fromisoformat('2011-11-04T00:05:23Z')
datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('20111104T000523')
datetime.datetime(2011, 11, 4, 0, 5, 23)
>>> datetime.fromisoformat('2011-W01-2T00:05:23.283')
datetime.datetime(2011, 1, 4, 0, 5, 23, 283000)
评论
上一个:夏令时和时区最佳做法 [已关闭]
评论