如何将 RFC 2822 日期/时间解析为 Python 日期时间?

发布于 2024-07-21 05:41:57 字数 194 浏览 6 评论 0原文

我有一个 RFC 2822 指定形式的日期 - 比如说 Fri, 15 May 2009 17:58:28 +0000,作为字符串。 在 Python 2.5 中是否有一种快速和/或标准的方法将其作为 datetime 对象获取? 我尝试生成 strptime 格式字符串,但 +0000 时区说明符使解析器感到困惑。

I have a date of the form specified by RFC 2822 -- say Fri, 15 May 2009 17:58:28 +0000, as a string. Is there a quick and/or standard way to get it as a datetime object in Python 2.5? I tried to produce a strptime format string, but the +0000 timezone specifier confuses the parser.

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

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

发布评论

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

评论(6

痴情 2024-07-28 05:41:57

问题是 parsedate 将忽略偏移量。

改为这样做:

from email.utils import parsedate_tz
print parsedate_tz('Fri, 15 May 2009 17:58:28 +0700')

The problem is that parsedate will ignore the offset.

Do this instead:

from email.utils import parsedate_tz
print parsedate_tz('Fri, 15 May 2009 17:58:28 +0700')
摘星┃星的人 2024-07-28 05:41:57

我想详细说明一下之前的答案。 email.utils.parsedateemail.utils.parsedate_tz 都返回元组,因为OP需要一个 datetime.datetime 对象,我添加这些示例是为了完整性:

from email.utils import parsedate
from datetime import datetime
import time

t = parsedate('Sun, 14 Jul 2013 20:14:30 -0000')
d1 = datetime.fromtimestamp(time.mktime(t))

或者:

d2 = datetime.datetime(*t[:6])

请注意,d1d2 都是简单的日期时间对象,没有存储时区信息。 如果您需要了解日期时间对象,请检查 tzinfo datetime() 参数。

或者,您可以使用 dateutil 模块

I'd like to elaborate on previous answers. email.utils.parsedate and email.utils.parsedate_tz both return tuples, since the OP needs a datetime.datetime object, I'm adding these examples for completeness:

from email.utils import parsedate
from datetime import datetime
import time

t = parsedate('Sun, 14 Jul 2013 20:14:30 -0000')
d1 = datetime.fromtimestamp(time.mktime(t))

Or:

d2 = datetime.datetime(*t[:6])

Note that d1 and d2 are both naive datetime objects, there's no timezone information stored. If you need aware datetime objects, check the tzinfo datetime() arg.

Alternatively you could use the dateutil module

嗫嚅 2024-07-28 05:41:57
from email.utils import parsedate
print parsedate('Fri, 15 May 2009 17:58:28 +0000')

文档

from email.utils import parsedate
print parsedate('Fri, 15 May 2009 17:58:28 +0000')

Documentation.

七度光 2024-07-28 05:41:57

看起来 Python 3.3 以后在 email.utils 中有一个新方法 parsedate_to_datetime 来处理中间步骤:

email.utils.parsedate_to_datetime(日期)

format_datetime() 的逆函数。 执行与 parsedate() 相同的功能,但是
成功返回日期时间。 如果输入日期的时区为-0000,
日期时间将是一个简单的日期时间,并且如果日期符合
对于 RFC,它将代表 UTC 时间,但没有指示
日期来自的消息的实际源时区。 如果
输入日期具有任何其他有效的时区偏移,日期时间将为
具有相应时区 tzinfo 的感知日期时间。

3.3 版本中的新增功能。

http://python.readthedocs.org/en /latest/library/email.util.html#email.utils.parsedate_to_datetime

It looks like Python 3.3 going forward has a new method parsedate_to_datetime in email.utils that takes care of the intermediate steps:

email.utils.parsedate_to_datetime(date)

The inverse of format_datetime(). Performs the same function as parsedate(), but on
success returns a datetime. If the input date has a timezone of -0000,
the datetime will be a naive datetime, and if the date is conforming
to the RFCs it will represent a time in UTC but with no indication of
the actual source timezone of the message the date comes from. If the
input date has any other valid timezone offset, the datetime will be
an aware datetime with the corresponding a timezone tzinfo.

New in version 3.3.

http://python.readthedocs.org/en/latest/library/email.util.html#email.utils.parsedate_to_datetime

装纯掩盖桑 2024-07-28 05:41:57

email.util 中有一个解析函数。
它解析所有有效的 RFC 2822 日期和一些特殊情况。

There is a parsedate function in email.util.
It parses all valid RFC 2822 dates and some special cases.

南冥有猫 2024-07-28 05:41:57

email.utils.parsedate_tz(日期)< /code>是要使用的函数。 以下是一些变化。

电子邮件日期/时间字符串 (RFC 5322RFC 2822RFC 1123) 到 unix 时间戳(以浮点秒为单位):

import email.utils
import calendar
def email_time_to_timestamp(s):
    tt = email.utils.parsedate_tz(s)
    if tt is None: return None
    return calendar.timegm(tt) - tt[9]

import time
print(time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(email_time_to_timestamp("Wed, 04 Jan 2017 09:55:45 -0800"))))
# 2017-01-04T17:55:45Z

确保您不使用 mktime (解释计算机本地时间中的 time_struct,不是世界标准时间); 使用 timegmmktime_tz 代替 (但请注意下一段中的 mktime_tz 警告)。

如果您确定您拥有 python 版本 2.7.4、3.2.4、3.3 或更高版本,那么您可以使用 email.utils.mktime_tz(tt) 而不是 calendar.timegm(tt) - tt[9]< /代码>。 在此之前,mktime_tz 在本地时区秋季夏令时转换期间调用时给出的时间不正确 (错误 14653)。

感谢 @jf-sebastian 提供有关 mktime 和 mktime_tz 的注意事项

电子邮件日期/时间字符串 (RFC 5322RFC 2822RFC 1123) 在 python 3.3 上“感知”datetime

在 python 3.3 及更高版本上,使用 email.utils.parsedate_to_datetime ,它返回一个具有原始区域偏移量的感知datetime

import email.utils
email.utils.parsedate_to_datetime(s)

print(email.utils.parsedate_to_datetime("Wed, 04 Jan 2017 09:55:45 -0800").isoformat())
# 2017-01-04T09:55:45-08:00

警告:如果时间落在闰秒,这将抛出ValueError,例如email.utils.parsedate_to_datetime( “2016 年 12 月 31 日星期六 15:59:60 -0800”)

电子邮件日期/时间字符串 (RFC 5322RFC 2822RFC 1123) 到 UTC 区域中的“aware”datetime

这只是转换为时间戳,然后转换为 UTC datetime

import email.utils
import calendar
import datetime
def email_time_to_utc_datetime(s):
    tt = email.utils.parsedate_tz(s)
    if tt is None: return None
    timestamp = calendar.timegm(tt) - tt[9]
    return datetime.datetime.utcfromtimestamp(timestamp)

print(email_time_to_utc_datetime("Wed, 04 Jan 2017 09:55:45 -0800").isoformat())
# 2017-01-04T17:55:45

电子邮件日期/时间字符串 (RFC 5322RFC 2822RFC 1123) 到 python “aware” datetime 并带有原始偏移量:

早于 python 3.2,python 没有附带 tzinfo 实现,所以这里有一个使用 dateutil.tz.tzoffset (pip install dateutil):

import email.utils
import datetime
import dateutil.tz
def email_time_to_datetime(s):
    tt = email.utils.parsedate_tz(s)
    if tt is None: return None
    tz = dateutil.tz.tzoffset("UTC%+02d%02d"%(tt[9]//60//60, tt[9]//60%60), tt[9])
    return datetime.datetime(*tt[:5]+(min(tt[5], 59),), tzinfo=tz)

print(email_time_to_datetime("Wed, 04 Jan 2017 09:55:45 -0800").isoformat())
# 2017-01-04T09:55:45-08:00

如果您使用的是 python 3.2,则可以使用内置的 tzinfo实现 datetime.timezonetz = datetime.timezone(datetime.timedelta(seconds=tt[9])) 而不是第三方dateutil.tz.tzoffset

再次感谢@jf-sebastian 有关固定闰秒的说明

email.utils.parsedate_tz(date) is the function to use. Following are some variations.

Email date/time string (RFC 5322, RFC 2822, RFC 1123) to unix timestamp in float seconds:

import email.utils
import calendar
def email_time_to_timestamp(s):
    tt = email.utils.parsedate_tz(s)
    if tt is None: return None
    return calendar.timegm(tt) - tt[9]

import time
print(time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(email_time_to_timestamp("Wed, 04 Jan 2017 09:55:45 -0800"))))
# 2017-01-04T17:55:45Z

Make sure you do not use mktime (which interprets the time_struct in your computer’s local time, not UTC); use timegm or mktime_tz instead (but beware caveat for mktime_tz in the next paragraph).

If you are sure that you have python version 2.7.4, 3.2.4, 3.3, or newer, then you can use email.utils.mktime_tz(tt) instead of calendar.timegm(tt) - tt[9]. Before that, mktime_tz gave incorrect times when invoked during the local time zone’s fall daylight savings transition (bug 14653).

Thanks to @j-f-sebastian for caveats about mktime and mktime_tz.

Email date/time string (RFC 5322, RFC 2822, RFC 1123) to “aware” datetime on python 3.3:

On python 3.3 and above, use email.utils.parsedate_to_datetime, which returns an aware datetime with the original zone offset:

import email.utils
email.utils.parsedate_to_datetime(s)

print(email.utils.parsedate_to_datetime("Wed, 04 Jan 2017 09:55:45 -0800").isoformat())
# 2017-01-04T09:55:45-08:00

Caveat: this will throw ValueError if the time falls on a leap second e.g. email.utils.parsedate_to_datetime("Sat, 31 Dec 2016 15:59:60 -0800").

Email date/time string (RFC 5322, RFC 2822, RFC 1123) to “aware” datetime in UTC zone:

This just converts to timestamp and then to UTC datetime:

import email.utils
import calendar
import datetime
def email_time_to_utc_datetime(s):
    tt = email.utils.parsedate_tz(s)
    if tt is None: return None
    timestamp = calendar.timegm(tt) - tt[9]
    return datetime.datetime.utcfromtimestamp(timestamp)

print(email_time_to_utc_datetime("Wed, 04 Jan 2017 09:55:45 -0800").isoformat())
# 2017-01-04T17:55:45

Email date/time string (RFC 5322, RFC 2822, RFC 1123) to python “aware” datetime with original offset:

Prior to python 3.2, python did not come with tzinfo implementations, so here an example using dateutil.tz.tzoffset (pip install dateutil):

import email.utils
import datetime
import dateutil.tz
def email_time_to_datetime(s):
    tt = email.utils.parsedate_tz(s)
    if tt is None: return None
    tz = dateutil.tz.tzoffset("UTC%+02d%02d"%(tt[9]//60//60, tt[9]//60%60), tt[9])
    return datetime.datetime(*tt[:5]+(min(tt[5], 59),), tzinfo=tz)

print(email_time_to_datetime("Wed, 04 Jan 2017 09:55:45 -0800").isoformat())
# 2017-01-04T09:55:45-08:00

If you are using python 3.2, you can use the builtin tzinfo implementation datetime.timezone: tz = datetime.timezone(datetime.timedelta(seconds=tt[9])) instead of the third-party dateutil.tz.tzoffset.

Thanks to @j-f-sebastian again for note on clamping the leap second.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文