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

时间:2009-05-19 21:03:05

标签: python parsing datetime time python-2.5

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

6 个答案:

答案 0 :(得分:32)

问题是parsedate会忽略偏移量。

请改为:

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

答案 1 :(得分:13)

我想详细说明之前的答案。 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() arg。

或者,您可以使用dateutil模块

答案 2 :(得分:12)

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

Documentation

答案 3 :(得分:8)

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

答案 4 :(得分:5)

看起来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

答案 5 :(得分:2)

email.utils.parsedate_tz(date)是要使用的功能。以下是一些变化。

电子邮件日期/时间字符串(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,而不是UTC);请改用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在本地时区的秋季夏令时转换(bug 14653)期间调用了错误的时间。

感谢@ j-f-sebastian caveats about mktime and 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("Sat, 31 Dec 2016 15:59:60 -0800")

电子邮件日期/时间字符串(RFC 5322RFC 2822RFC 1123)到UTC区域中的“感知”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.tzoffsetpip 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

再次感谢@ j-f-sebastian for note on clamping the leap second

相关问题