2011-12-19 2 views
34

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

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

Проблема с установкой смещения UTC.

Согласно docs, classmethod 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.

Это где я получаю lost- Каким tzinfo является абстрактным классом, и как я должен реализовать его?


(Примечание: В PHP это так просто, как timestamp = date(DATE_RFC3339);, поэтому я не могу понять, почему подход Python настолько запутанным ...)

+0

Только что нашел этот вопрос: [Время ISO (ISO 8601) в Python?] (Http: // stackoverflow.com/questions/2150739/iso-time-iso-8601-in-python) – Yarin

ответ

7

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

+0

@ ruah- спасибо, я пропустил эти примеры - класс 'LocalTimezone()' сделал трюк. – Yarin

+0

@ Ярин: Добро пожаловать! – ruakh

+0

@gene_wood: Надеюсь, вы не против, я вернул ваше редактирование. Проблема в том, что то, что вы внедрили, не соответствует тому, что OP действительно хотел. – ruakh

28

Часовые пояса являются боль, которая, вероятно, почему они решили не включать их в библиотеку 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'

+0

@ monkut- thanks- Класс pytz выглядит как другая реализация, которая будет работать, но я закончил использование примера, включенного в документы, за ответ за руах , – Yarin

+0

@ monkut- +1 ваш второй пример тоже хорошая идея – Yarin

+0

не возвращает микросекунды для меня: -/ –

0

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

14

В 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, то вы могли бы define a simple tzinfo subclass as shown in the docs to represent UTC timezone:

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.

+0

Руки вниз, лучший ответ для Python 3.3+ –

+0

Технически, ISO 8601 и RFC 3339 не являются 100% совместимый ... существуют некоторые различия, например, что ISO 8601 позволяет либо знак минус, либо дефис для части смещения UTC, тогда как RFC 3339 _only_ позволяет дефис. Каждая реализация '.isoformat()', которую я видел до сих пор (только пара), перекрывает RFC 3339, но хорошо осознавать различия – villapx

+1

@villapx: rfc 3339 является профилем ISO 8601. Это происходит что 'datetime.isoformat()' является RFC 3339 для дат-времени, относящегося к часовому поясу (именно поэтому я его использовал). – jfs

1

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

Чтобы добавить UTC смещение: импорта DateTime импорт 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

вам не нужен модуль 'pytz', если вы хотите только часовой пояс UTC. Это просто [define utc tzinfo] (http://stackoverflow.com/a/25421145/4279) – jfs

+0

Спасибо. Я сохраню ваш ответ, когда мне понадобится решение stdlib. UTC был самым коротким для демонстрации. ОП специально не просил об этом. 'pytz' знает обо всех часовых поясах и их DST, которые я считаю полезными. –

+0

Примечание: ['get_localzone()' в моем ответе] (http://stackoverflow.com/a/27987813/4279) возвращает puts часовой пояс, соответствующий локальному часовому поясу. – jfs

5

Я боролся с форматом RFC3339 даты и времени много, но я нашел подходящее решение для преобразования da te_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 ​​) использовать строки даты и строки даты в удобном для использования формате.

0

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

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 
Смежные вопросы