it-swarm-pt.tech

Gerar timestamp RFC 3339 em Python

Eu estou tentando gerar um RFC 3339 timestamp UTC em Python. Até agora eu pude fazer o seguinte:

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

Meu problema é com a configuração do deslocamento UTC.

De acordo com o docs , o método de classe datetime.now([tz]), recebe um argumento tz opcional, em que tz must be an instance of a class tzinfo subclass e datetime.tzinfo são an abstract base class for time zone information objects.

É aqui que me perco ... Como é que o tzinfo é uma classe abstrata e como posso implementá-lo? 


(NOTE: Em PHP é tão simples quanto timestamp = date(DATE_RFC3339);, e é por isso que não consigo entender porque a abordagem do Python é tão complicada ...)

47
Yarin

Mais abaixo no mesmo documento que você vinculou, explica como implementá-lo, dando alguns exemplos, incluindo código completo para uma classe UTC (representando UTC), uma classe FixedOffset (representando um fuso horário com um deslocamento fixo de UTC, ao contrário de um fuso horário com DST e outros), e alguns outros.

7
ruakh

Fusos horários são uma dor, e é provavelmente por isso que eles optaram por não incluí-los na biblioteca datetime.

tente pytz, ele tem o tzinfo que você está procurando: http://pytz.sourceforge.net/

Você precisa primeiro criar o objeto datetime, depois aplicar o fuso horário como abaixo, e então a saída .isoformat() incluirá o deslocamento UTC conforme desejado:

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

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

Ou apenas use o UTC e lance um "Z" (para o fuso horário Zulu) no final para marcar o "fuso horário" como UTC.

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

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

36
monkut

No 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'

Em versões mais antigas do Python, se tudo que você precisa é de um objeto datetime que represente a hora atual no UTC, então você pode definir uma subclasse tzinfo simples como mostrado nos documentos para representar o fuso horário UTC :

from datetime import datetime

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

Você também pode usar tzlocal module para obter o pytz timezone representando seu fuso horário local:

#!/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'))

Funciona no Python 2 e 3.

22
jfs

Eu lutei muito com formato de data e hora RFC3339, mas eu encontrei uma solução adequada para converter date_string <=> datetime_object em ambas as direções.

Você precisa de dois módulos externos diferentes, porque um deles só é capaz de fazer a conversão em uma direção (infelizmente):

primeira instalação:

Sudo pip install rfc3339
Sudo pip install iso8601

então inclua:

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

Para não precisar lembrar qual módulo é para qual direção, escrevi duas funções auxiliares simples:

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

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

que dentro do seu código você pode facilmente usar assim:

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

Heureka! Agora você pode facilmente ( haha ​​) usar suas strings de data e data em um formato utilizável.

5
MenschMarcus

O pacote pytz está disponível para o Python 2.X e 3.X. Ele implementa subclasses concretas de tzinfo, entre outros serviços, então você não precisa.

Para adicionar um deslocamento UTC: Import datetime Import pytz

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

E agora isso:

print utc_dt.isoformat()

imprimiria:

2011-12-18T20:46:00.392227+00:00
1
Eli_B

Você pode realmente usar o módulo datetime embutido. Como @ruakhmenciona , há exemplos na página Que mostram como. Se você olhar para a seção sobre tzinfo você Verá um longo exemplo mostrando muitos casos de uso diferentes. Aqui está o código para o Que você está procurando, que é gerar um timestamp RTC 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
0
gene_wood

Outro utilitário útil com o qual acabei de começar a trabalhar: dateutil library para manipulação de fuso horário e análise de data. Recomendado em torno de SO, incluindo este answer

0
Yarin