803

我需要将RFC 3339字符串解析"2008-09-03T20:56:35.450686Z"为 Python 的datetime类型。

strptime在Python标准库里找过,但不是很方便。

做这个的最好方式是什么?

4

28 回答 28

592

isoparse来自python-dateutil 的函数

python-dateutildateutil.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 格式解析器,但fromisoformat故意不是. 请参阅后一个函数的文档以了解此警告性警告。(见这个答案)。

于 2013-03-05T15:44:16.223 回答
381

从 Python 3.7 开始,datetime标准库有一个用于反转datetime.isoformat().

类方法 datetime.fromisoformat(date_string)

以and发出的格式之一返回datetime对应于 a 的 a 。date_stringdate.isoformat()datetime.isoformat()

具体来说,此函数支持以下格式的字符串:

YYYY-MM-DD[*HH[:MM[:SS[.mmm[mmm]]]][+HH:MM[:SS[.ffffff]]]]

where*可以匹配任何单个字符。

注意:这不支持解析任意 ISO 8601 字符串 - 它仅用作datetime.isoformat().

例子:

>>> from datetime import datetime
>>> datetime.fromisoformat('2011-11-04')
datetime.datetime(2011, 11, 4, 0, 0)

…</p>

请务必阅读文档中的警告!

于 2018-04-11T20:32:10.420 回答
212

请注意,在 Python 2.6+ 和 Py3K 中,%f 字符会捕获微秒。

>>> datetime.datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")

在这里查看问题

于 2008-09-24T15:45:02.013 回答
181

这里的几个答案 建议使用时区来解析 RFC 3339 或 ISO 8601 日期时间,就像问题中展示的那样: datetime.datetime.strptime

2008-09-03T20:56:35.450686Z

这是一个坏主意。

假设您想要支持完整的 RFC 3339 格式,包括支持除零以外的 UTC 偏移量,那么这些答案建议的代码不起作用。事实上,它不能工作,因为使用解析 RFC 3339 语法strptime是不可能的。Python 的 datetime 模块使用的格式字符串无法描述 RFC 3339 语法。

问题是UTC偏移量。RFC 3339 Internet 日期/时间格式要求每个日期时间都包含一个 UTC 偏移量,并且这些偏移量可以是Z(“祖鲁时间”的缩写)+HH:MM-HH:MM格式,如+05:00or -10:30

因此,这些都是有效的 RFC 3339 日期时间:

  • 2008-09-03T20:56:35.450686Z
  • 2008-09-03T20:56:35.450686+05:00
  • 2008-09-03T20:56:35.450686-10:30

唉,格式字符串使用strptime并且strftime没有与 RFC 3339 格式中的 UTC 偏移相对应的指令。他们支持的指令的完整列表可以在https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior找到,列表中包含的唯一 UTC 偏移指令是%z

%z

格式为 +HHMM 或 -HHMM 的 UTC 偏移量(如果对象是幼稚的,则为空字符串)。

示例:(空)、+0000、-0400、+1030

这与 RFC 3339 偏移量的格式不匹配,实际上,如果我们尝试%z在格式字符串中使用并解析 RFC 3339 日期,我们将失败:

>>> from datetime import datetime
>>> datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686Z' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
>>> datetime.strptime("2008-09-03T20:56:35.450686+05:00", "%Y-%m-%dT%H:%M:%S.%f%z")
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686+05:00' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'

(实际上,上面的内容正是您在 Python 3 中看到的。在 Python 2 中,我们会因为更简单的原因而失败,即在 Python 2 中strptime根本没有实现该%z指令。)

这里推荐的多个答案都可以通过在其格式字符串中strptime包含一个文字来解决此问题,该字符串与提问者的示例日期时间字符串匹配(并丢弃它,生成一个没有时区的对象):ZZdatetime

>>> datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)

由于这会丢弃原始日期时间字符串中包含的时区信息,因此我们是否应该将这个结果视为正确是值得怀疑的。但更重要的是,因为这种方法涉及将特定的 UTC 偏移量硬编码到格式字符串中,所以当它尝试解析任何具有不同 UTC 偏移量的 RFC 3339 日期时间时,它会阻塞:

>>> datetime.strptime("2008-09-03T20:56:35.450686+05:00", "%Y-%m-%dT%H:%M:%S.%fZ")
Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.4/_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.4/_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2008-09-03T20:56:35.450686+05:00' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'

除非您确定您只需要支持祖鲁时间的 RFC 3339 日期时间,而不是具有其他时区偏移量的日期时间,否则不要使用strptime. 请改用此处答案中描述的许多其他方法之一。

于 2015-06-07T17:53:25.920 回答
80

试试iso8601模块;它正是这样做的。

python.org wiki 上的WorkingWithTime页面上还提到了其他几个选项。

于 2008-09-24T15:38:17.147 回答
46

从 Python 3.7 开始,strptime 支持 UTC 偏移量 ( source ) 中的冒号分隔符。所以你可以使用:

import datetime
datetime.datetime.strptime('2018-01-31T09:24:31.488670+00:00', '%Y-%m-%dT%H:%M:%S.%f%z')

编辑:

正如 Martijn 所指出的,如果您使用 isoformat() 创建了 datetime 对象,您可以简单地使用datetime.fromisoformat().

于 2018-01-31T09:52:55.233 回答
36

你得到的确切错误是什么?是不是像下面这样?

>>> 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)
于 2008-09-24T15:19:27.817 回答
32
import re
import datetime
s = "2008-09-03T20:56:35.450686Z"
d = datetime.datetime(*map(int, re.split(r'[^\d]', s)[:-1]))
于 2008-09-24T15:27:24.380 回答
31

评论之一中的一个简单选项:替换'Z''+00:00'- 并使用 Python 3.7+ 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)

虽然strptime可以将字符解析'Z'为 UTC,但fromisoformat速度更快 ~ x40(另请参见:更快的 strptime):

%timeit datetime.fromisoformat(s.replace('Z', '+00:00'))
346 ns ± 22.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f%z')
14.2 µs ± 452 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit dateutil.parser.parse(s)
80.1 µs ± 3.32 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

(Windows 10 上的 Python 3.8.7 x64)

于 2020-07-07T06:34:40.563 回答
22

如今,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())
于 2015-02-15T16:47:44.013 回答
21

只需使用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())

文档

于 2017-02-28T18:14:17.067 回答
15

我发现ciso8601是解析 ISO 8601 时间戳的最快方法。顾名思义,它是用 C 实现的。

import ciso8601
ciso8601.parse_datetime('2014-01-09T21:48:00.921000+05:30')

GitHub Repo README显示了与其他答案中列出的所有其他库相比,它们的速度提高了 10 倍以上。

我的个人项目涉及大量的 ISO 8601 解析。能够切换通话并以 10 倍的速度运行真是太好了。:)

编辑:我已经成为 ciso8601 的维护者。现在比以往任何时候都快!

于 2017-03-27T18:41:55.233 回答
13

如果不想使用 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)
于 2014-03-27T22:50:16.067 回答
13

如果您使用 Django,它提供了dateparse 模块,该模块接受一堆类似于 ISO 格式的格式,包括时区。

如果您不使用 Django 并且不想使用此处提到的其他库之一,则可以将dateparse 的 Django 源代码调整为您的项目。

于 2015-09-30T21:42:22.070 回答
9

我为 ISO 8601 标准编写了一个解析器并将其放在 GitHub 上:https ://github.com/boxed/iso8601 。此实现支持规范中的所有内容,但持续时间、间隔、周期性间隔和 Python 的 datetime 模块支持的日期范围之外的日期除外。

包括测试!:P

于 2013-03-02T13:31:49.793 回答
9

这适用于 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)
于 2015-03-11T06:03:35.673 回答
8

我是iso8601utils的作者。它可以在 GitHubPyPI上找到。以下是解析示例的方法:

>>> from iso8601utils import parsers
>>> parsers.datetime('2008-09-03T20:56:35.450686Z')
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
于 2016-10-26T05:20:18.800 回答
7

datetime.datetime在不安装第三方模块的情况下,将类似 ISO 8601 的日期字符串转换为所有支持的 Python 版本中的 UNIX 时间戳或对象的一种直接方法是使用SQLite 的日期解析器

#!/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
于 2016-08-25T16:16:26.243 回答
7

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')
于 2016-09-08T09:42:18.843 回答
6

另一种方法是使用 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的文档中也提到了这个函数:

第三方包 dateutil 中提供了功能更全的 ISO 8601 解析器 dateutil.parser.isoparse。

于 2019-09-24T12:32:41.400 回答
4

因为 ISO 8601 允许存在许多可选的冒号和破折号,所以基本上CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]. 如果你想使用 strptime,你需要先去掉这些变化。

目标是生成一个 UTC 日期时间对象。


如果您只想要一个适用于带有 Z 后缀的 UTC 的基本案例,例如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-04002008-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" )


如果您的系统不支持%zstrptime 指令(您会看到类似 的内容ValueError: 'z' is a bad directive in format '%Y%m%dT%H%M%S.%f%z'),那么您需要手动从Z(UTC) 偏移时间。注意%z在 python 版本 < 3 中可能无法在您的系统上运行,因为它取决于 c 库支持,该支持因系统/python 构建类型(即 Jython、Cython 等)而异。

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
于 2016-06-28T19:54:18.820 回答
4

如果pandas无论如何都要使用,我可以Timestamppandas. 在那里你可以

ts_1 = pd.Timestamp('2020-02-18T04:27:58.000Z')    
ts_2 = pd.Timestamp('2020-02-18T04:27:58.000')

Rant:令人难以置信的是,我们仍然需要担心 2021 年的日期字符串解析之类的事情。

于 2021-07-28T14:22:38.257 回答
2

对于适用于 2.X 标准库的内容,请尝试:

calendar.timegm(time.strptime(date.split(".")[0]+"UTC", "%Y-%m-%dT%H:%M:%S%Z"))

calendar.timegm 是 time.mktime 的缺失 gm 版本。

于 2011-07-21T06:47:19.800 回答
2

如果解析无效的日期字符串,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
于 2013-08-09T15:53:22.103 回答
2
于 2018-09-24T18:21:02.863 回答
1

感谢伟大的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))
于 2016-03-14T15:05:53.017 回答
0

最初我尝试过:

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)
于 2019-05-15T01:32:49.600 回答
-1
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.

于 2016-08-09T10:17:22.723 回答