Генерация метки времени RFC 3339 в Python - PullRequest
49 голосов
/ 19 декабря 2011

Я пытаюсь сгенерировать RFC 3339 UTC в Python. До сих пор я мог сделать следующее:

>>> d = datetime.datetime.now()
>>> print d.isoformat('T')
2011-12-18T20:46:00.392227

Моя проблема с настройкой смещения UTC.

Согласно документам метод класса datetime.now([tz]) принимает необязательный аргумент tz, где tz must be an instance of a class tzinfo subclass, а datetime.tzinfo равно an abstract base class for time zone information objects.

Вот где я заблудился. Почему tzinfo - абстрактный класс, и как мне его реализовать?


( ПРИМЕЧАНИЕ: В PHP это так же просто, как timestamp = date(DATE_RFC3339);, поэтому я не могу понять, почему подход Python настолько запутан ...)

Ответы [ 8 ]

39 голосов
/ 19 декабря 2011

Часовые пояса - это боль, поэтому, вероятно, они решили не включать их в библиотеку datetime.

попробуйте pytz, у вас есть tzinfo, которую вы ищете: http://pytz.sourceforge.net/

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

d = datetime.datetime.utcnow()
d_with_timezone = d.replace(tzinfo=pytz.UTC)
d_with_timezone.isoformat()

'2017-04-13T14: 34: 23.111142 + 00: 00 '

Или просто используйте UTC и добавьте "Z" (для Zulu часовой пояс) в конце, чтобы отметить "часовой пояс""как UTC.

d = datetime.datetime.utcnow() # <-- get time in UTC
print d.isoformat("T") + "Z"

'2017-04-13T14: 34: 23.111142Z'

25 голосов
/ 16 января 2015

В Python 3.3 +:

>>> from datetime import datetime, timezone                                
>>> local_time = datetime.now(timezone.utc).astimezone()
>>> local_time.isoformat()
'2015-01-16T16:52:58.547366+01:00'

Если в старых версиях Python вам нужен только осведомленный объект datetime, представляющий текущее время в UTC, тогда вы можете определить простой подкласс tzinfo, как показанов документах для обозначения часового пояса UTC :

from datetime import datetime

utc_now = datetime.now(utc)
print(utc_now.isoformat('T'))
# -> 2015-05-19T20:32:12.610841+00:00

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

#!/usr/bin/env python
from datetime import datetime
from tzlocal import get_localzone # $ pip install tzlocal

now = datetime.now(get_localzone())
print(now.isoformat('T'))

Работает как на Python 2, так и 3.

7 голосов
/ 19 декабря 2011

Далее в том же документе, на который вы ссылались, объясняется, как его реализовать, приводятся некоторые примеры, включая полный код для класса UTC (представляющего UTC), класса FixedOffset(представляющий часовой пояс с фиксированным смещением от UTC, в отличие от часового пояса с DST и прочее) и некоторые другие.

5 голосов
/ 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

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

1 голос
/ 19 мая 2015

Пакет pytz доступен для Python 2.X и 3.X. Он реализует конкретные подклассы tzinfo, среди других сервисов, поэтому вам не нужно.

Чтобы добавить смещение UTC: дата импорта время импорт pytz

dt = datetime.datetime(2011, 12, 18, 20, 46, 00, 392227)
utc_dt = pytz.UTC.localize(dt)

А теперь вот это:

print utc_dt.isoformat()

напечатает:

2011-12-18T20:46:00.392227+00:00
0 голосов
/ 13 июня 2019

На современном (3.x) python, чтобы получить время RFC 3339 UTC, все, что вам нужно сделать, это использовать datetime и эту единственную строку (не требуются сторонние модули):

import datetime
datetime.datetime.now(datetime.timezone.utc).isoformat()

Результат примерно такой: '2019-06-13T15: 29: 28.972488 + 00: 00'

Эта строка ISO 8601 также совместима с RFC3339.

0 голосов
/ 09 сентября 2016

Вы действительно можете использовать встроенный datetime модуль. Как @ ruakh упоминает , в страница, которая показывает, как. Если вы посмотрите в раздел tzinfo вы будете посмотрите длинный пример, показывающий много разных вариантов использования. Вот код для одного вы ищете, чтобы сгенерировать временную метку UTC RFC 3339.

from datetime import tzinfo, timedelta, datetime
import time as _time

ZERO = timedelta(0)
STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
    DSTOFFSET = timedelta(seconds=-_time.altzone)
else:
    DSTOFFSET = STDOFFSET

DSTDIFF = DSTOFFSET - STDOFFSET


class LocalTimezone(tzinfo):

    def utcoffset(self, dt):
        if self._isdst(dt):
            return DSTOFFSET
        else:
            return STDOFFSET

    def dst(self, dt):
        if self._isdst(dt):
            return DSTDIFF
        else:
            return ZERO

    def tzname(self, dt):
        return _time.tzname[self._isdst(dt)]

    def _isdst(self, dt):
        tt = (dt.year, dt.month, dt.day,
              dt.hour, dt.minute, dt.second,
              dt.weekday(), 0, 0)
        stamp = _time.mktime(tt)
        tt = _time.localtime(stamp)
        return tt.tm_isdst > 0

Local = LocalTimezone()

d = datetime.now(Local)
print d.isoformat('T')

# which returns
# 2014-04-28T15:44:45.758506-07:00
0 голосов
/ 19 декабря 2011

Еще одна полезная утилита, с которой я только начал работать: dateutil библиотека для обработки часовых поясов и анализа дат.Рекомендуется около SO, включая этот ответ

...