Преобразование времени RFC 3339 в стандартную временную метку Python - PullRequest
17 голосов
/ 21 декабря 2009

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

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

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

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

Ответы [ 11 ]

22 голосов
/ 21 декабря 2009

Вы не включили пример, но если у вас нет 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, поэтому некоторые люди еще не знают, что она там есть.

Редактировать : Функция 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
9 голосов
/ 21 декабря 2009

Нет встроенных, афаик.

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

Имеет лицензию BSD.

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

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

8 голосов
/ 21 декабря 2009

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

7 голосов
/ 13 марта 2016

Я много боролся с форматом даты и времени 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

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

6 голосов
/ 21 декабря 2009

http://bugs.python.org/issue15873 (копия http://bugs.python.org/issue5207)

Похоже, встроенного пока нет.

5 голосов
/ 22 декабря 2009

feedparser.py предоставляет надежный / расширяемый способ анализа различных форматов даты, которые могут встречаться в реальных каналах atom / 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)
3 голосов
/ 26 августа 2016

Если вы используете Django, вы можете использовать функцию 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>)
2 голосов
/ 19 августа 2015

попробуй это, у меня нормально работает

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')
1 голос
/ 07 июня 2016

Используя 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")))))

В этом примере временные зоны или микросекунды пропускаются как «0», но может потребоваться дополнительная проверка ошибок. Ура, Алекс

0 голосов
/ 27 августа 2012

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

...