2009-05-19 3 views
21

У меня есть дата формы, указанной в RFC 2822 - скажем Fri, 15 May 2009 17:58:28 +0000, как строка. Есть ли быстрый и/или стандартный способ получить его как объект datetime в Python 2.5? Я попытался создать строку формата strptime, но спецификатор часового пояса +0000 смущает парсер.Как разобрать дату/время RFC 2822 в дату и время Python?

ответ

27

Проблема заключается в том, что в парседате игнорируется смещение.

ли это вместо:

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

Существует функция анализа в email.util. Он анализирует все действительные даты RFC 2822 и некоторые специальные случаи.

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

Documentation.

+0

+1 Я не знал об этой функции, действительно опрятной. –

+0

Спасибо; это делает трюк. :) – millenomi

7

Я хотел бы остановиться на предыдущих ответов. email.utils.parsedate и email.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]) 

Обратите внимание, что d1 и d2 оба являются наивными объектами DateTime , информация о часовом поясе отсутствует. Если вам нужны осведомленные объекты datetime, проверьте аргумент tzinfodatetime().

В качестве альтернативы можно использовать модуль

4

dateutil Это выглядит как Python 3.3 в будущем имеет новый метод parsedate_to_datetime в email.utils, который заботится о промежуточных шагов:

email.utils. parsedate_to_datetime (date)

Обратный формат format_datetime(). Выполняет ту же функцию, что и parsedate(), но на успех возвращает дату и время. Если дата ввода имеет временную зону от -0000, , то время datetime будет наивным datetime, и если дата соответствует RFC, она будет представлять время в UTC, но без указания фактического часового пояса сообщения дата исходит. Если дата ввода имеет любое другое допустимое смещение временной зоны, дата-время будет значащее время-время с соответствующим часовым поясом tzinfo.

Новое в версии 3.3.

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

1

email.utils.parsedate_tz(date) функция для использования. Ниже приведены некоторые варианты.

Email строка даты/времени (RFC 5322, RFC 2822, RFC 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); используйте вместо этого timegm или mktime_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.

Дата E-mail строки времени/(RFC 5322, RFC 2822, RFC 1123), чтобы «знать,» datetime на Python 3.3:

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

Дата Email Строка времени/(RFC 5322, RFC 2822, RFC 1123), чтобы «знать,» datetime в UTC зоне:

Это просто превращается в отметку времени и затем 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/(RFC 5322, RFC 2822,) на «знаток» питона datetime с исходным смещением:

До Python 3.2, питон не пришел с 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 

Если вы используете питон 3.2, вы можете использовать встроенную tzinfo реализации datetime.timezone: tz = datetime.timezone(datetime.timedelta(seconds=tt[9])) вместо сторонний dateutil.tz.tzoffset.

Благодаря @ j-f-sebastian снова for note on clamping the leap second.