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

发布于 2024-08-15 19:01:17 字数 498 浏览 6 评论 0原文

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

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

我从 ATOM 规范 中注意到,ATOM日期包含时区偏移量(Z),但就我而言,Z 之后没有任何内容,所以我想我们可以假设 GMT。

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

Is there an easy way to convert an RFC 3339 time into a regular Python timestamp?

I've got a script which is reading an ATOM feed and I'd like to be able to compare the timestamp of an item in the ATOM feed to the modification time of a file.

I notice from the ATOM spec, that ATOM dates include a time zone offset (Z<a number>) but, in my case, there's nothing after the Z so I guess we can assume GMT.

I suppose I could parse the time with a regex of some sort but I was hoping Python had a built-in way of doing it that I just haven't been able to find.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

风尘浪孓 2024-08-22 19:01:17

您没有包含示例,但如果您没有 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

You don't include an example, but if you don't have a Z-offset or timezone, and assuming you don't want durations but just the basic time, then maybe this will suit you:

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)

The strptime() function was added to the datetime module in Python 2.5 so some people don't yet know it's there.

Edit: The time.strptime() function has existed for a while though, and works about the same to give you a struct_time value:

>>> 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
拥抱影子 2024-08-22 19:01: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

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

I struggled with RFC3339 datetime format a lot, but I found a suitable solution to convert date_string <=> datetime_object in both directions.

You need two different external modules, because one of them is is only able to do the conversion in one direction (unfortunately):

first install:

sudo pip install rfc3339
sudo pip install iso8601

then include:

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

For not needing to remember which module is for which direction, I wrote two simple helper functions:

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

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

which inside your code you can easily use like this:

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

Heureka! Now you can easily (haha) use your date strings and date strings in a useable format.

天暗了我发光 2024-08-22 19:01:17

新的 datetime.fromisoformat(date_string) 方法是Python 3.7 中添加 将解析大多数 RFC 3339 时间戳,包括带有时间的时间戳区域偏移。这不是完整的实现,因此请务必测试您的用例。

>>> 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)))

The new datetime.fromisoformat(date_string) method which was added in Python 3.7 will parse most RFC 3339 timestamps, including those with time zone offsets. It's not a full implementation, so be sure to test your use case.

>>> 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)))
长安忆 2024-08-22 19:01:17

没有内置的,据我所知。

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

它是 BSD 许可的。

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

(已编辑所以很明显我没有写:-)

No builtin, afaik.

feed.date.rfc3339
This is a Python library module with functions for converting timestamp strings in RFC 3339 format to Python time float values, and vice versa. RFC 3339 is the timestamp format used by the Atom feed syndication format.

It is BSD-licensed.

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

(Edited so it's clear I didn't write it. :-)

戒ㄋ 2024-08-22 19:01:17

如果您使用的是 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>)

If you're using Django, you could use Django's function 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>)
纵情客 2024-08-22 19:01:17

对我来说最简单的解决方案是 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

The simplest solution for me has been dateutil python standart library.

from dateutil.parser import parse

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

Output:

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

If you don't need the timezone element, just simply set timezone info to None

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

The output is a nice and clean datetime object:

2020-11-23 11:08:23.022277
说好的呢 2024-08-22 19:01:17

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

http://pypi.python.org/pypi/iso8601/ seems to be able to parse iso 8601, which RFC 3339 is a subset of, maybe this could be useful, but again, not built-in.

游魂 2024-08-22 19:01:17

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

看起来目前还没有内置的。

http://bugs.python.org/issue15873 (duplicate of http://bugs.python.org/issue5207 )

Looks like there isn't a built-in as of yet.

玩套路吗 2024-08-22 19:01:17

feedparser.py 提供了强大/可扩展的方法来解析实际中可能遇到的各种日期格式-世界原子/RSS 提要:

>>> 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)

feedparser.py provides robust/extensible way to parse various date formats that may be encountered in real-world atom/rss feeds:

>>> 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)
最后的乘客 2024-08-22 19:01:17

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

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')

try this, it works fine for me

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

or

datetime_obj = datetime.strptime("Mon, 01 Jun 2015 16:41:40 GMT", '%a, %d %b %Y %H:%M:%S GMT')
墨小墨 2024-08-22 19:01:17

在另一个问题中遇到了很棒的 dateutil.parser 模块,并在我的 RFC3339 问题上尝试了它,它似乎可以处理所有问题与这个问题中的任何其他回答相比,我更理智地提出这个问题。

Came across the awesome dateutil.parser module in another question, and tried it on my RFC3339 problem, and it appears to handle everything I throw at it with more sanity that any of the other responses in this question.

青巷忧颜 2024-08-22 19:01:17

使用 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”,但可能需要额外的错误检查。
干杯,亚历克斯

Using Python 3, you can use RegEx to break the RFC 3339 timestamp into its components.
Then, directly create the datetime object, no additional modules needed:

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")))))

This example theads missing timezones or microseconds as "0" but might need additional error checking.
Cheers, Alex

小ぇ时光︴ 2024-08-22 19:01:17

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

它的用法非常简单:

from google.api_core.datetime_helpers import to_rfc3339

rfc3339_str = to_rfc3339(datetime.now())

它们甚至有一个以 from_rfc3339from_rfc3339_nanos 的相反方式工作的函数。

You could use a Google API Core package. They have a really straightforward Datetime to RFC 3339 conversion function. You can find more info in their docs.

Its usage is as simple as:

from google.api_core.datetime_helpers import to_rfc3339

rfc3339_str = to_rfc3339(datetime.now())

They even have a function that works the other way around from_rfc3339 and from_rfc3339_nanos.

格子衫的從容 2024-08-22 19:01:17

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

import arrow

date_string = "2015-11-24 00:00:00+00:00"
my_datetime = arrow.get(date_string).datetime

I have been doing a deep dive in dateimes and RFC3339 and recently come across the arrow library and have just used and solved my problem:

import arrow

date_string = "2015-11-24 00:00:00+00:00"
my_datetime = arrow.get(date_string).datetime
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文