110

我必须将时区感知字符串转换"2012-11-01T04:16:13-04:00"为 Pythondatetime对象。

我看到了dateutil具有解析功能的模块,但我真的不想使用它,因为它添加了依赖项。

那么我该怎么做呢?我尝试过类似以下的方法,但没有运气。

datetime.datetime.strptime("2012-11-01T04:16:13-04:00", "%Y-%m-%dT%H:%M:%S%Z")
4

7 回答 7

127

从 Python 3.7 开始,datetime.datetime.fromisoformat()可以处理您的格式:

>>> import datetime
>>> datetime.datetime.fromisoformat('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))

在较旧的 Python 版本中,您不能,除非没有大量艰苦的手动时区定义。

Python 不包含时区数据库,因为它会很快过时。相反,Python 依赖于可以具有更快发布周期的外部库来为您提供正确配置的时区。

作为副作用,这意味着时区解析也需要是一个外部库。如果dateutil对您来说太重,请iso8601改用它,它会很好地解析您的特定格式:

>>> import iso8601
>>> iso8601.parse_date('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=<FixedOffset '-04:00'>)

iso8601是一个惊人的4KB 小。比较 totpython-dateutil的 148KB。

从 Python 3.2 开始,Python可以处理简单的基于偏移量的时区,并将%z解析时间戳中的时区偏移量。这意味着对于 ISO 8601 时间戳,您必须在时区中删除:-hhmm+hhmm:

>>> from datetime import datetime
>>> iso_ts = '2012-11-01T04:16:13-04:00'
>>> datetime.strptime(''.join(iso_ts.rsplit(':', 1)), '%Y-%m-%dT%H:%M:%S%z')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000)))

在Python 问题 15873中正在跟踪缺乏正确的 ISO 8601 解析。

于 2012-11-01T17:13:35.110 回答
63

这是使用 dateutil 包的日期时间对象的 Python文档。

from dateutil.parser import parse

get_date_obj = parse("2012-11-01T04:16:13-04:00")
print get_date_obj
于 2016-04-12T07:18:09.597 回答
22

原始问题中的代码有两个问题:时区中不应该有 a并且“时区作为偏移量”:的格式字符串是小写而不是大写。%z%Z

这在Python v3.6中对我有用

>>> from datetime import datetime
>>> t = datetime.strptime("2012-11-01T04:16:13-0400", "%Y-%m-%dT%H:%M:%S%z")
>>> print(t)
2012-11-01 04:16:13-04:00
于 2017-06-14T01:48:00.597 回答
5

你可以这样转换。

date = datetime.datetime.strptime('2019-3-16T5-49-52-595Z','%Y-%m-%dT%H-%M-%S-%f%z')
date_time = date.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
于 2019-03-25T11:04:15.447 回答
3

您可以创建一个时区不感知对象,然后替换它tzinfo并使其成为时区感知DateTime对象。

from datetime import datetime
import pytz

unware_time = datetime.strptime("2012-11-01 04:16:13", "%Y-%m-%d %H:%M:%S")
aware_time = unaware_time.replace(tzinfo=pytz.UTC)
于 2021-06-24T14:57:14.490 回答
1

Mohideen bin Mohammed提出的使用 dateutil 的建议绝对是最好的解决方案,即使它确实需要一个小型库。在那里使用其他方法容易出现各种形式的失败。这是一个很好的功能。

from dateutil.parser import parse


def parse_date_convert(date, fmt=None):
    if fmt is None:
        fmt = '%Y-%m-%d %H:%M:%S' # Defaults to : 2022-08-31 07:47:30
    get_date_obj = parse(str(date))
    return str(get_date_obj.strftime(fmt))

dates = ['2022-08-31T07:47:30Z','2022-08-31T07:47:29.098Z','2017-05-27T07:20:18.000-04:00','2012-11-01T04:16:13-04:00']

for date in dates:
    print(f'Before: {date}  After: {parse_date_convert(date)}')

结果:

Before: 2022-08-31T07:47:30Z  After: 2022-08-31 07:47:30
Before: 2022-08-31T07:47:29.098Z  After: 2022-08-31 07:47:29
Before: 2017-05-27T07:20:18.000-04:00  After: 2017-05-27 07:20:18
Before: 2012-11-01T04:16:13-04:00  After: 2012-11-01 04:16:13

尝试了各种形式,例如切片分割替换 TZ,如下所示:

dates = ['2022-08-31T07:47:30Z','2022-08-31T07:47:29.098Z','2017-05-27T07:20:18.000-04:00','2012-11-01T04:16:13-04:00']

for date in dates:
    print(f'Before: {date}  After: {date.replace("T", " ").replace("Z", "")}')

你仍然得到低于标准的结果。像下面

Before: 2022-08-31T07:47:30Z  After: 2022-08-31 07:47:30
Before: 2022-08-31T07:47:29.098Z  After: 2022-08-31 07:47:29.098
Before: 2017-05-27T07:20:18.000-04:00  After: 2017-05-27 07:20:18.000-04:00
Before: 2012-11-01T04:16:13-04:00  After: 2012-11-01 04:16:13-04:00
于 2021-03-27T20:26:34.793 回答
1

我是 Python 新手,但找到了一种转换方法

2017-05-27T07:20:18.000-04:00

2017-05-27T07:20:18无需下载新的实用程序。

from datetime import datetime, timedelta

time_zone1 = int("2017-05-27T07:20:18.000-04:00"[-6:][:3])
>>returns -04

item_date = datetime.strptime("2017-05-27T07:20:18.000-04:00".replace(".000", "")[:-6], "%Y-%m-%dT%H:%M:%S") + timedelta(hours=-time_zone1)

我敢肯定有更好的方法可以做到这一点,而无需过多地切割字符串,但这完成了工作。

于 2017-06-01T14:39:54.420 回答