2009-12-21 4 views
13

Есть ли простой способ преобразования времени RFC 3339 в обычную временную метку Python?Преобразование даты RFC 3339 в стандартную временную метку Python

У меня есть скрипт, который читает фид ATOM, и я хотел бы иметь возможность сравнивать метку времени элемента в фиде ATOM с временем изменения файла.

я замечаю из ATOM spec, что даты ATOM включают смещение часового пояса (Z<a number>), но, в моем случае, нет ничего после того, как Z, так что я думаю, мы можем предположить, GMT.

Я полагаю, что я мог бы анализировать время с каким-то регулярным выражением, но я надеялся, что у Python есть встроенный способ сделать это, что я просто не смог найти.

+2

Если вы читали RFC 3339 спецификации, вы увидите, что действительно только часовой пояс значения: (0) голый «Z», то есть отметка времени - UTC; или (1) смещение формы «[+ -] \ d \ d: \ d \ d", например, «+02: 00» или «-08: 00». Обратите внимание, что смещение «+00: 00» означает то же самое, что и «Z». Для получения дополнительной информации прочитайте спецификацию RFC 3339: http://tools.ietf.org/html/rfc3339 – steveha

+0

Ошибка Python: [issue15873: datetime: добавить возможность разбора RFC 3339 дат и времени] (http: //bugs.python .org/issue15873) – jfs

+0

related: [Преобразование временных меток со смещением в datetime obj с использованием strptime] (http://stackoverflow.com/q/12281975/4279) – jfs

ответ

9

No builtin, afaik.

feed.date.rfc3339 Это библиотечный модуль Python с функциями для преобразования временных меток строк в формате RFC 3339 для значений с плавающей точкой Python времени, и наоборот. RFC 3339 - это формат времени, используемый форматом синдикации Atom-фида.

Лицензия на BSD.

http://home.blarg.net/~steveha/pyfeed.html

(ред так ясно, что я не писал. :-)

+0

PyFeed делает именно то, что мне нужно, благодаря функции tf_from_timestamp() в feed.date.rfc3339 –

+1

Кроме того, я написал библиотеки PyFeed (и Xe), и я выхожу здесь на StackOverflow, поэтому, если у вас есть какие-либо вопросы по этому поводу, я был бы рад ответить на них. – steveha

+0

Обратите внимание, что PyFeed можно использовать для анализа фида Atom. Он использует xml.dom.minidom для выполнения фактического разбора, а затем распаковывает структуру дерева XML в приятные удобные классы. Хм, я должен положить Xe и PyFeed на PyPI. – steveha

8

http://pypi.python.org/pypi/iso8601/, кажется, быть в состоянии разобрать ISO 8601, который RFC 3339 является подмножеством, может быть, это может быть полезно, но опять же, не встроенный.

+0

Время плавает и struct_time не осведомлены о часовом поясе. Поскольку RFC 3339 требует UTC-совместимых часовых поясов, которые в Python означают не наивные объекты 'datetime', это единственный разумный вариант. – Tobu

21

Вы не включают в себя пример, но если вы не имеете Z-смещение или часовой пояс, и если вы не хотите, длительности, но только основное время, то, возможно, это вам подойдет:

import datetime as dt 
>>> dt.datetime.strptime('1985-04-12T23:20:50.52', '%Y-%m-%dT%H:%M:%S.%f') 
datetime.datetime(1985, 4, 12, 23, 20, 50, 520000) 

Функция strptime() была добавлена ​​в модуль datetime в Python 2.5, поэтому некоторые люди еще не знают, что это есть.

Edit: time.strptime() функция существует некоторое время, хотя, и работает примерно то же самое, чтобы дать вам значение struct_time:

>>> ts = time.strptime('1985-04-12T23:20:50.52', '%Y-%m-%dT%H:%M:%S.%f') 
>>> ts 
time.struct_time(tm_year=1985, tm_mon=4, tm_mday=12, tm_hour=23, tm_min=20, tm_sec=50, tm_wday=4, tm_yday=102, tm_isdst=-1) 
>>> time.mktime(ts) 
482210450.0 
+7

+1 для решения с использованием стандартной библиотеки! – jathanism

+8

Это не сработает. Методы, не относящиеся к часовому поясу, не совместимы с RFC 3339. – Yarin

+0

Ярин, очевидно, но ваша жалоба должна быть с использованием исходного вопроса «RFC 3339», так как мой ответ действительно касался его актуального вопроса, где он отмечает, что у него нет часового пояса ... –

5

feedparser.py обеспечивает надежную/расширяемый способ синтаксического анализа различных форматов дат, которые могут встретиться в реальном мире атом/RSS:

>>> from feedparser import _parse_date as parse_date 
>>> parse_date('1985-04-12T23:20:50.52Z') 
time.struct_time(tm_year=1985, tm_mon=4, tm_mday=12, tm_hour=23, tm_min=20, 
       tm_sec=50, tm_wday=4, tm_yday=102, tm_isdst=1) 
+1

Это кажется гораздо приятнее, чем «всплывающие окна», предлагаемые PyFeed. –

+2

cool-NR, если у вас есть значение с плавающей точкой, вы можете вызвать 'time.gmtime()' и получить значение 'struct_time'. И гораздо проще делать относительные времена с использованием значения времени плавания; через два дня это просто 'tf + 2 * seconds_per_day' (где' seconds_per_day' равно 24 * 60 * 60). «Struct_time» Python отлично подходит для проверки (какой день недели?), Но ужасно неудобно для вычислений. – steveha

+0

ссылка сломана - должно быть http://code.google.com/p/feedparser/source/browse/trunk/feedparser/feedparser.py? – Yarin

0

Перешел через классный dateutil.parser модуль в другой вопрос и попробовал его по моей проблеме RFC3339, и, похоже, он обрабатывает все, что я бросаю на него с большей здравомыслием, что любые другие ответы в этом вопросе.

+1

Единственная проблема в том, что он также анализирует * не-даты * значения, такие как «сейчас» –

1

попробовать это, она отлично работает для меня

datetime_obj = datetime.strptime("2014-01-01T00:00:00Z", '%Y-%m-%dT%H:%M:%SZ') 

или

datetime_obj = datetime.strptime("Mon, 01 Jun 2015 16:41:40 GMT", '%a, %d %b %Y %H:%M:%S GMT') 
+2

, он не поддерживает численное смещение utc: '+ HHMM'. Второй пример: [rfc 3339] (https://tools.ietf.org/html/rfc3339#section-5.6); это [rfc 5322] (https://tools.ietf.org/html/rfc5322#section-3.3) – jfs

3

Я боролся с форматом RFC3339 даты и времени много, но я нашел подходящее решение для преобразования DATE_STRING < => datetime_object в в обоих направлениях.

Вам понадобятся два различных внешних модулей, потому что один из них только в состоянии выполнить преобразование в одном направлении (к сожалению):

первой установки:

sudo pip install rfc3339 
sudo pip install iso8601 

затем включают в себя:

import datetime  # for general datetime object handling 
import rfc3339  # for date object -> date string 
import iso8601  # for date string -> date object 

Для того, чтобы не помнить, какой модуль для этого направления, я написал две простые вспомогательные функции:

def get_date_object(date_string): 
    return iso8601.parse_date(date_string) 

def get_date_string(date_object): 
    return rfc3339.rfc3339(date_object) 

который внутри вашего кода вы можете легко использовать, как это:

input_string = '1989-01-01T00:18:07-05:00' 
test_date = get_date_object(input_string) 
# >>> datetime.datetime(1989, 1, 1, 0, 18, 7, tzinfo=<FixedOffset '-05:00' datetime.timedelta(-1, 68400)>) 

test_string = get_date_string(test_date) 
# >>> '1989-01-01T00:18:07-05:00' 

test_string is input_string # >>> True 

Эврика! Теперь вы можете легко (haha ​​) использовать строки даты и строки даты в удобном для использования формате.

1

Используя Python 3, вы можете использовать RegEx, чтобы разбить временную метку RFC 3339 на ее компоненты. Затем, непосредственно создавать объект типа DateTime, никаких дополнительных модулей, необходимые:

import re 
import datetime 

def parse_rfc3339(dt): 
    broken = re.search(r'([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]+))?(Z|([+-][0-9]{2}):([0-9]{2}))', dt) 
    return(datetime.datetime(
     year = int(broken.group(1)), 
     month = int(broken.group(2)), 
     day = int(broken.group(3)), 
     hour = int(broken.group(4)), 
     minute = int(broken.group(5)), 
     second = int(broken.group(6)), 
     microsecond = int(broken.group(8) or "0"), 
     tzinfo = datetime.timezone(datetime.timedelta(
      hours = int(broken.group(10) or "0"), 
      minutes = int(broken.group(11) or "0"))))) 

Этот пример theads отсутствует или часовые пояса микросекунд как «0», но, возможно, потребуется дополнительная проверка ошибок. Cheers, Алекс

+1

Предположительно, это тоже работало бы на Python 2. – Flimm

2

Если вы используете Django, вы могли бы использовать Джанго функция parse_datetime:

>>> from django.utils.dateparse import parse_datetime 
>>> parse_datetime("2016-07-19T07:30:36+05:00") 
datetime.datetime(2016, 7, 19, 7, 30, 36, tzinfo=<django.utils.timezone.FixedOffset object at 0x101c0c1d0>)