Como você converte um objeto time.struct_time em um objeto datetime?

288

Como você converte um time.struct_timeobjeto Python em um datetime.datetimeobjeto?

Eu tenho uma biblioteca que fornece a primeira e uma segunda biblioteca que deseja a segunda.

static_rtti
fonte

Respostas:

384

Use time.mktime () para converter a tupla de tempo (no horário local) em segundos desde a época, depois use datetime.fromtimestamp () para obter o objeto datetime.

from datetime import datetime
from time import mktime

dt = datetime.fromtimestamp(mktime(struct))
Rod Hyde
fonte
45
Note que isso falha antes de 1900. Vocês modernos nunca se lembram dessa limitação!
mlissner
3
isso vai perder os tm_isdstdados? Eu acho que sim, o que resulta datetime objeto permanece ingênuo a ponto de voltar Noneno .dst()mesmo se struct.tm_isdsté 1.
N611x007
3
Isso geralmente funciona. No entanto, ela falhará se a tupla de tempo estiver além dos valores que o mktime aceita, por exemplo, para o valor (1970, 1, 1, 0, 0, 0, 0, 1, -1). Eu encontrei isso depois de analisar o cabeçalho Date em uma solicitação HTTP que retornou essa tupla.
user3820547
3
@richvdh: C padrão especifica que mktime()deve ser levado tm_isdstem consideração e Python time.mktime()chama a mktime()função C no CPython. mktime()pode escolher a hora local errada quando for ambígua (por exemplo, durante a transição de final de horário de verão ("fall back")) se struct.tm_isdstestiver -1ou se mktime()na plataforma fornecida ignorar a entrada tm_isdst . Além disso, se o fuso horário local tiver um deslocamento utc diferente no passado e C mktime()não usar um banco de dados tz histórico que possa fornecer os valores antigos de deslocamento utc, também mktime()poderá retornar um valor errado (por exemplo, por uma hora).
JFS
1
@ naxa: se mktime()não ignorar tm_isdstna plataforma especificada (na minha), fromtimestamp()definitivamente perde a informação: o objeto ingênuo retornado que datetimerepresenta a hora local pode ser ambíguo (timestamp -> hora local é determinístico (se ignorarmos os segundos bissextos), mas local time -> timestamp may be ambiguous e.g., during end-of-DST transition). Also, fromtimestamp () `pode escolher uma compensação se o ele não usa um banco de dados tz histórico UTC errado.
JFS
123

Como isso:

>>> structTime = time.localtime()
>>> datetime.datetime(*structTime[:6])
datetime.datetime(2009, 11, 8, 20, 32, 35)
Nadia Alramli
fonte
3
Não se esqueça de tempo # Import, datetime
jhwist
7
@jhwist - algumas coisas que as pessoas podem ser confiáveis para descobrir isso por conta própria :)
orip
14
@rodling the *e **sintaxe permite expandir um objeto do tipo listy ou dicty para separar argumentos - é uma das minhas peças favoritas de adorável Python. Veja docs.python.org/2/tutorial/… para obter mais informações
OrganicPanda
10
Lembre-se de que isso fornecerá um ValueError se o struct_time tiver um segundo, por exemplo:t=time.strptime("30 Jun 1997 22:59:60", "%d %b %Y %H:%M:%S"); datetime.datetime(*t[:6])
berdario
7
@berdario: para retornar valores compatíveis com datetime: datetime(*t[:5]+(min(t[5], 59),))por exemplo, para aceitar "2015-06-30 16:59:60 PDT".
JFS
37

Esta não é uma resposta direta à sua pergunta (que já foi respondida muito bem). No entanto, depois de várias vezes me morder no fundamento várias vezes, não posso enfatizar o suficiente para que você olhe atentamente o que seu objeto time.struct_time está fornecendo, em comparação com o que outros campos de tempo podem ter.

Supondo que você tenha um objeto time.struct_time e outra string de data / hora, compare os dois e verifique se você não está perdendo dados e criando inadvertidamente um objeto ingetime datetime, quando é possível fazê-lo.

Por exemplo, o excelente módulo feedparser retornará um campo "publicado" e poderá retornar um objeto time.struct_time em seu campo "Published_parsed":

time.struct_time(tm_year=2013, tm_mon=9, tm_mday=9, tm_hour=23, tm_min=57, tm_sec=42, tm_wday=0, tm_yday=252, tm_isdst=0)

Agora observe o que você realmente recebe com o campo "publicado".

Mon, 09 Sep 2013 19:57:42 -0400

Pela barba de Stallman ! Informações sobre fuso horário!

Nesse caso, o homem preguiçoso pode querer usar o excelente módulo dateutil para manter as informações do fuso horário:

from dateutil import parser
dt = parser.parse(entry["published"])
print "published", entry["published"])
print "dt", dt
print "utcoffset", dt.utcoffset()
print "tzinfo", dt.tzinfo
print "dst", dt.dst()

o que nos dá:

published Mon, 09 Sep 2013 19:57:42 -0400
dt 2013-09-09 19:57:42-04:00
utcoffset -1 day, 20:00:00
tzinfo tzoffset(None, -14400)
dst 0:00:00

Pode-se então usar o objeto datetime com reconhecimento de fuso horário para normalizar o tempo todo para UTC ou o que você achar incrível.

lisdexia
fonte
7
Todos os *_parsedcampos de análise de feeds já estão normalizados para UTC, pois podem ser verificados na documentação de análise de data, portanto isso é redundante.
itorres
1
@ itorres: Se eu entendi, esta resposta não é sobre normalizar para UTC, mas sobre manter as informações de fuso horário em um datetimeobjeto que é perdido quando feedparseranalisa datas de string brutas.
davidag 26/08/19