У меня есть дата формы, указанной в RFC 2822 - скажем Fri, 15 May 2009 17:58:28 +0000
, как строка. Есть ли быстрый и/или стандартный способ получить его как объект datetime
в Python 2.5? Я попытался создать строку формата strptime, но спецификатор часового пояса +0000 смущает парсер.Как разобрать дату/время RFC 2822 в дату и время Python?
ответ
Проблема заключается в том, что в парседате игнорируется смещение.
ли это вместо:
from email.utils import parsedate_tz
print parsedate_tz('Fri, 15 May 2009 17:58:28 +0700')
Существует функция анализа в email.util. Он анализирует все действительные даты RFC 2822 и некоторые специальные случаи.
from email.utils import parsedate
print parsedate('Fri, 15 May 2009 17:58:28 +0000')
Я хотел бы остановиться на предыдущих ответов. 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, проверьте аргумент tzinfo
datetime()
.
В качестве альтернативы можно использовать модуль
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
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.
+1 Я не знал об этой функции, действительно опрятной. –
Спасибо; это делает трюк. :) – millenomi