将 RFC 3339 时间转换为标准 Python 时间戳

问题描述 投票:0回答:15

有没有一种简单的方法可以将 RFC 3339 时间转换为常规 Python 时间戳?

我有一个正在读取 ATOM feed 的脚本,我希望能够将 ATOM feed 中项目的时间戳与文件的修改时间进行比较。

我从 ATOM 规范中注意到,ATOM 日期包含时区偏移量 (

Z<a number>
),但就我而言,
Z
之后没有任何内容,所以我想我们可以假设 GMT。

我想我可以用某种正则表达式来解析时间,但我希望Python有一种内置的方法来做到这一点,但我一直找不到。

python datetime rfc3339
15个回答
37
投票

您没有提供示例,但如果您没有 Z 偏移量或时区,并且假设您不需要持续时间而只需要基本时间,那么也许这会适合您:

import datetime as dt
>>> dt.datetime.strptime('1985-04-12T23:20:50.52', '%Y-%m-%dT%H:%M:%S.%f')
datetime.datetime(1985, 4, 12, 23, 20, 50, 520000)

strptime() 函数已添加到 Python 2.5 中的 datetime 模块中,因此有些人还不知道它的存在。

编辑: time.strptime() 函数已经存在了一段时间,并且其工作原理大致相同,可以为您提供 struct_time 值:

>>> ts = time.strptime('1985-04-12T23:20:50.52', '%Y-%m-%dT%H:%M:%S.%f')
>>> ts
time.struct_time(tm_year=1985, tm_mon=4, tm_mday=12, tm_hour=23, tm_min=20, tm_sec=50, tm_wday=4, tm_yday=102, tm_isdst=-1)
>>> time.mktime(ts)
482210450.0

17
投票

我在 RFC3339 日期时间格式方面遇到了很多困难,但我找到了一个合适的解决方案来双向转换 date_string <=> datetime_object。

您需要两个不同的外部模块,因为其中一个只能在一个方向上进行转换(不幸的是):

首次安装:

sudo pip install rfc3339
sudo pip install iso8601

然后包括:

import datetime     # for general datetime object handling
import rfc3339      # for date object -> date string
import iso8601      # for date string -> date object

为了不需要记住哪个模块对应哪个方向,我编写了两个简单的辅助函数:

def get_date_object(date_string):
  return iso8601.parse_date(date_string)

def get_date_string(date_object):
  return rfc3339.rfc3339(date_object)

您可以在代码中轻松使用它,如下所示:

input_string = '1989-01-01T00:18:07-05:00'
test_date = get_date_object(input_string)
# >>> datetime.datetime(1989, 1, 1, 0, 18, 7, tzinfo=<FixedOffset '-05:00' datetime.timedelta(-1, 68400)>)

test_string = get_date_string(test_date)
# >>> '1989-01-01T00:18:07-05:00'

test_string is input_string # >>> True

赫尤卡!现在您可以轻松地(哈哈)使用您的日期字符串和可用格式的日期字符串。


16
投票

[Python 3.7 中添加的][2] [datetime.fromisoformat(date_string)][1] 方法将解析大多数 RFC 3339 时间戳,包括具有时区偏移量的时间戳,但值得注意的是不是“祖鲁时间”(UTC 表示为Z 而不是 +00:00)。这不是完整的实现,因此请务必测试您的用例。

但是,在版本 3.11 [3] 中,其功能已扩展为包括对祖鲁时间的支持。

Python 版本 3.7、3.8、3.9 和 3.10

>>> from datetime import datetime
>>> datetime.fromisoformat('2011-11-04')
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-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)))
>>> datetime.fromisoformat('2011-11-04T00:05:23Z')  
ValueError: Invalid isoformat string: '2011-11-04T00:05:23Z'

Python 3.11

>>> datetime.fromisoformat('2011-11-04T00:05:23Z') 
datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc)
  1. https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat
  2. https://docs.python.org/3/whatsnew/3.7.html#datetime
  3. https://docs.python.org/3/whatsnew/3.11.html#datetime

14
投票

没有内置,据我所知。

feed.date.rfc3339 这是一个 Python 库模块,具有将 RFC 3339 格式的时间戳字符串转换为 Python 时间浮点值的函数,反之亦然。 RFC 3339 是 Atom feed 联合格式使用的时间戳格式。

它是 BSD 许可的。

http://home.blarg.net/~steveha/pyfeed.html

(已编辑,很明显不是我写的。:-)


11
投票

如果你使用Django,你可以使用Django的函数

parse_datetime
:

>>> from django.utils.dateparse import parse_datetime
>>> parse_datetime("2016-07-19T07:30:36+05:00")
datetime.datetime(2016, 7, 19, 7, 30, 36, tzinfo=<django.utils.timezone.FixedOffset object at 0x101c0c1d0>)

11
投票

对我来说最简单的解决方案是dateutil python 标准库。

from dateutil.parser import parse

dt = "2020-11-23T11:08:23.022277705Z"
print(parse(dt))

输出:

2020-11-23 11:08:23.022277+00:00

如果您不需要时区元素,只需将时区信息设置为None

print(parse(t).replace(tzinfo=None))

输出是一个漂亮且干净的日期时间对象:

2020-11-23 11:08:23.022277

8
投票

http://pypi.python.org/pypi/iso8601/似乎能够解析iso 8601,RFC 3339是它的子集,也许这可能有用,但同样,不是内置的。


6
投票

http://bugs.python.org/issue15873(重复http://bugs.python.org/issue5207

看起来目前还没有内置。


5
投票

feedparser.py提供了强大/可扩展的方法来解析现实世界中的atom/rss feed中可能遇到的各种日期格式:

>>> from feedparser import _parse_date as parse_date
>>> parse_date('1985-04-12T23:20:50.52Z')
time.struct_time(tm_year=1985, tm_mon=4, tm_mday=12, tm_hour=23, tm_min=20,
                 tm_sec=50, tm_wday=4, tm_yday=102, tm_isdst=1)

5
投票

试试这个,对我来说效果很好

datetime_obj =  datetime.strptime("2014-01-01T00:00:00Z", '%Y-%m-%dT%H:%M:%SZ')

datetime_obj = datetime.strptime("Mon, 01 Jun 2015 16:41:40 GMT", '%a, %d %b %Y %H:%M:%S GMT')

2
投票

在另一个问题中遇到了很棒的 dateutil.parser 模块,并在我的 RFC3339 问题上尝试了它,它似乎比这个问题中的任何其他响应更理智地处理我扔给它的所有内容。


2
投票

使用 Python 3,您可以使用 RegEx 将 RFC 3339 时间戳分解为其组件。 然后,直接创建日期时间对象,不需要额外的模块:

import re
import datetime

def parse_rfc3339(dt):
    broken = re.search(r'([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]+))?(Z|([+-][0-9]{2}):([0-9]{2}))', dt)
    return(datetime.datetime(
        year = int(broken.group(1)),
        month = int(broken.group(2)),
        day = int(broken.group(3)),
        hour = int(broken.group(4)),
        minute = int(broken.group(5)),
        second = int(broken.group(6)),
        microsecond = int(broken.group(8) or "0"),
        tzinfo = datetime.timezone(datetime.timedelta(
            hours = int(broken.group(10) or "0"),
            minutes = int(broken.group(11) or "0")))))

此示例缺少时区或微秒为“0”,但可能需要额外的错误检查。 干杯,亚历克斯


2
投票

您可以使用 Google API Core 包。他们有一个非常简单的日期时间到 RFC 3339 转换功能。您可以在他们的文档中找到更多信息。

它的用法很简单:

from google.api_core.datetime_helpers import to_rfc3339

rfc3339_str = to_rfc3339(datetime.now())

他们甚至有一个相反的功能

from_rfc3339
from_rfc3339_nanos



0
投票

我一直在深入研究日期时间和 RFC3339,最近遇到了 arrow 库,并且刚刚使用并解决了我的问题:

import arrow

date_string = "2015-11-24 00:00:00+00:00"
my_datetime = arrow.get(date_string).datetime
© www.soinside.com 2019 - 2024. All rights reserved.