【发布时间】:2010-12-01 02:45:42
【问题描述】:
有没有一种简单的方法可以在 Python 中解析 HTTP 日期字符串?根据the standard,有几种格式化HTTP日期字符串的方法;该方法应该能够处理这个问题。
换句话说,我想将“Wed, 23 Sep 2009 22:15:29 GMT”之类的字符串转换为 python 时间结构。
【问题讨论】:
标签: python http datetime parsing
有没有一种简单的方法可以在 Python 中解析 HTTP 日期字符串?根据the standard,有几种格式化HTTP日期字符串的方法;该方法应该能够处理这个问题。
换句话说,我想将“Wed, 23 Sep 2009 22:15:29 GMT”之类的字符串转换为 python 时间结构。
【问题讨论】:
标签: python http datetime parsing
从 Python 3.3 开始,email.utils.parsedate_to_datetime 可以解析 RFC 5322 时间戳(又名 IMF-fixdate,Internet 消息格式固定长度格式,HTTP-date 的 RFC 7231 的子集)。
>>> from email.utils import parsedate_to_datetime
...
... s = 'Sun, 06 Nov 1994 08:49:37 GMT'
... parsedate_to_datetime(s)
0: datetime.datetime(1994, 11, 6, 8, 49, 37, tzinfo=datetime.timezone.utc)
还有无证的http.cookiejar.http2time可以实现如下:
>>> from datetime import datetime, timezone
... from http.cookiejar import http2time
...
... s = 'Sun, 06 Nov 1994 08:49:37 GMT'
... datetime.utcfromtimestamp(http2time(s)).replace(tzinfo=timezone.utc)
1: datetime.datetime(1994, 11, 6, 8, 49, 37, tzinfo=datetime.timezone.utc)
它在 Python 2.4 中作为 cookielib.http2time 引入,用于处理以相同格式表示的 Cookie Expires 指令。
【讨论】:
httplib.HTTPMessage(filehandle).getdate(headername)
httplib.HTTPMessage(filehandle).getdate_tz(headername)
mimetools.Message(filehandle).getdate()
rfc822.parsedate(datestr)
rfc822.parsedate_tz(datestr)
注意:
你可以这样做,如果你只有那一段字符串并且你想解析它:
>>> from rfc822 import parsedate, parsedate_tz
>>> parsedate('Wed, 23 Sep 2009 22:15:29 GMT')
(2009, 9, 23, 22, 15, 29, 0, 1, 0)
>>>
但让我通过 mime 消息来举例说明:
import mimetools
import StringIO
message = mimetools.Message(
StringIO.StringIO('Date:Wed, 23 Sep 2009 22:15:29 GMT\r\n\r\n'))
>>> m
<mimetools.Message instance at 0x7fc259146710>
>>> m.getdate('Date')
(2009, 9, 23, 22, 15, 29, 0, 1, 0)
或通过 http 消息(响应)
>>> from httplib import HTTPMessage
>>> from StringIO import StringIO
>>> http_response = HTTPMessage(StringIO('Date:Wed, 23 Sep 2009 22:15:29 GMT\r\n\r\n'))
>>> #http_response can be grabbed via urllib2.urlopen(url).info(), right?
>>> http_response.getdate('Date')
(2009, 9, 23, 22, 15, 29, 0, 1, 0)
对吗?
>>> import urllib2
>>> urllib2.urlopen('https://fw.io/').info().getdate('Date')
(2014, 2, 19, 18, 53, 26, 0, 1, 0)
好了,现在我们更多地了解日期格式、mime 消息、mime 工具及其 Python 实现 ;-)
无论如何,看起来比使用 email.utils 解析 http 标头更好。
【讨论】:
>>> import email.utils as eut
>>> eut.parsedate('Wed, 23 Sep 2009 22:15:29 GMT')
(2009, 9, 23, 22, 15, 29, 0, 1, -1)
如果你想要一个datetime.datetime 对象,你可以这样做:
def my_parsedate(text):
return datetime.datetime(*eut.parsedate(text)[:6])
【讨论】:
Sunday, 06-Nov-94 08:49:37 GMT,但 2616 表示客户端必须能够解析 RFC 850 日期(叹气)。
email.utils.parsedate is email.Utils.parsedate -> True 看来 Utils 是一个惰性加载器。
0 表示1970-01-01T00:00:00Z——它是世界各地的同一时间实例(本地时钟显示不同的值,但时间戳完全相同)。除非输入时间字符串是 UTC (GMT);你应该use mktime_tz(parsedate_tz()) instead -- 否则时区信息会丢失。
email.utils.parsedate_to_datetime
>>> import datetime
>>> datetime.datetime.strptime('Wed, 23 Sep 2009 22:15:29 GMT', '%a, %d %b %Y %H:%M:%S GMT')
datetime.datetime(2009, 9, 23, 22, 15, 29)
【讨论】:
email.utils.parse 更健壮,但它的透明度也较低。