No Python, como você converte um objeto `datetime` em segundos?

226

Desculpas pela pergunta simples ... Sou novo no Python ... Pesquisei e nada parece estar funcionando.

Eu tenho vários objetos de data e hora e quero calcular o número de segundos desde um horário fixo no passado para cada um (por exemplo, desde 1 de janeiro de 1970).

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

Isso parece diferenciar apenas as datas que têm dias diferentes:

t.toordinal()

Qualquer ajuda é muito apreciada.

Nathan Lippi
fonte
2
Eu provavelmente converter tanto a S desde época e de lá ir: int(t.timestamp())
nerdwaller
para a operação oposta ir aqui: Convert-segundos-desde-época-to-a-data e hora-objeto
Trevor Boyd Smith

Respostas:

233

Para a data especial de 1º de janeiro de 1970, há várias opções.

Para qualquer outra data inicial, você precisa obter a diferença entre as duas datas em segundos. Subtrair duas datas fornece um timedeltaobjeto que, a partir do Python 2.7, tem uma total_seconds()função.

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

A data de início geralmente é especificada no UTC; portanto, para obter os resultados adequados, o datetimefeed desta fórmula também deve estar no UTC. Se você datetimeainda não está no UTC, será necessário convertê-lo antes de usá-lo ou anexar uma tzinfoclasse com o deslocamento adequado.

Conforme observado nos comentários, se você tiver um tzinfoanexo ao seu datetime, também precisará de um na data de início ou a subtração falhará; para o exemplo acima, eu adicionaria tzinfo=pytz.utcse estivesse usando o Python 2 ou tzinfo=timezone.utcse estivesse usando o Python 3.

Mark Ransom
fonte
1
Agora, o Python me avisa: "TypeError: não é possível subtrair os tempos de deslocamento e ingestão de deslocamento" Qual é a melhor solução para corrigir isso?
Aaron Ash
2
@Charybdis, tente datetime.datetime(1970,1,1,tzinfo=pytz.utc).
Mark Ransom
9
Considere usar: datetime.datetime.utcfromtimestamp(0) usei isso para obter a 'época' facilmente. Observe que a época nem sempre é a mesma em todos os sistemas.
DA
3
Tenha muito cuidado com os fusos horários aqui. Estou no UTC + 2, o que significa que a saída time.time()e datetime.now() - datetime(1970, 1, 1)diferem em 7200 segundos. Prefiro usar (t - datetime.datetime.fromtimestamp(0)).total_seconds(). Você não usar utcfromtimestamp(0)se você quiser converter uma data e hora no seu fuso horário local.
Carl
2
@DA: Python não suporta épocas não POSIX . Todos os sistemas em que o python trabalha usam a mesma época: 1970-01-01 00:00:00 UTC
jfs
130

Para obter o tempo Unix (segundos desde 1 de janeiro de 1970):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0
Mark Byers
fonte
22
tenha cuidado ao usar o time.mktime, pois ele expressa a hora local e depende da plataforma #
Shih-Wen Su
7
Tenha cuidado, de fato. Mordeu-me a bunda grande tempo
Arg
assume que té uma hora local. O deslocamento UTC para o fuso horário local pode ter sido diferente no passado e se mktime()(biblioteca C) não tiver acesso a dados históricos do fuso horário em uma determinada plataforma do que pode falhar ( pytzé uma maneira portátil de acessar o banco de dados tz). Além disso, hora local pode ser, por exemplo ambígua, durante as transições DST - você precisa de informações adicionais para disambiguate por exemplo, se você sabe que data consecutiva / valores de tempo deve aumentar em um arquivo de log
jfs
1
Tenha cuidado ao usar isso com tempos que tenham frações de segundo. time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())resulta em uma 1564819506.0queda silenciosa dos milissegundos, mas datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(resposta de Andrzej Pronobis) resulta no 1564819506.912resultado esperado.
Alex
128

A partir do Python 3.3, isso se torna super fácil com o datetime.timestamp()método. Obviamente, isso só será útil se você precisar do número de segundos entre 1970-01-01 UTC.

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

O valor de retorno será um valor flutuante representando frações pares de segundo. Se a data e hora for ingênua do fuso horário (como no exemplo acima), será assumido que o objeto data e hora represente a hora local, ou seja, será o número de segundos da hora atual no seu local até 01-01-2009 UTC.

Andrzej Pronobis
fonte
3
Quem votou mal, poderia explicar por quê?
Andrzej Pronobis
5
Eu suponho que o voto negativo é devido à tag python-2.7 na pergunta (é apenas um palpite).
JFS
3
Essa deve ser a resposta aceita / a resposta aceita deve ser atualizada de acordo.
DreamFlasher 12/09/16
11
Hora de atualizar eu acho;)
DreamFlasher
é possível calcular essa distância a partir de outra data de início? (eu
pretendo
29

Talvez fora de tópico: para obter o horário do UNIX / POSIX do datetime e convertê-lo novamente:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

Observe que diferentes fusos horários têm impacto nos resultados, por exemplo, meus retornos atuais de TZ / DST:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

portanto, deve-se considerar a normalização para o UTC usando as versões UTC das funções.

Observe que o resultado anterior pode ser usado para calcular o deslocamento UTC do seu fuso horário atual. Neste exemplo, é + 1h, ou seja, UTC + 0100.

Referências:

Robert Lujo
fonte
mktime()pode falhar . Em geral, você precisa pytzconverter a hora local em utc, para obter o carimbo de data / hora do POSIX.
JFS
calendar.timegm () parece ser a versão UTC de time.mktime ()
frankster
27

int (t.strftime("%s")) também funciona

dan3
fonte
1
Funciona para mim no Python 2.7, com import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(conforme especificado pelo OP). Mas, realmente, duvido que% s seja um formato de hora adicionado recentemente.
dan3
1
@ dan3: errado. %snão é suportado (pode funcionar em algumas plataformas, se tfor um objeto de data e hora ingênuo que representa a hora local e se a biblioteca C local tiver acesso ao banco de dados tz, caso contrário, o resultado poderá estar errado). Não use.
JFS
%snão está documentado em nenhum lugar. Eu o semeio em código real e fiquei imaginando o que é isso e procure na documentação e não existe %s. Existe apenas com S grande apenas pelos segundos.
VStoykov
13

dos documentos python:

timedelta.total_seconds()

Retorne o número total de segundos contidos na duração. Equivalente a

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

calculado com a divisão verdadeira ativada.

Observe que, por intervalos de tempo muito grandes (mais de 270 anos na maioria das plataformas), esse método perde a precisão de microssegundos.

Essa funcionalidade é nova na versão 2.7.

Michael
fonte
1
há um pequeno problema com o cálculo, ele deve ser 10 6 em vez de 10 * 6 ... td.microsegundos + (td.seconds + td.days * 24 * 3600) * 10 6) / 10 ** 6
sdu
@sdu great catch - o asterisco duplo está na minha resposta, mas o stackoverflow o consome, tenta corrigir apenas o texto.
Michael
2

Para converter um objeto de data e hora que representa a hora no UTC em carimbo de data e hora POSIX :

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

Para converter um objeto de data e hora que representa a hora no fuso horário local em carimbo de data / hora do POSIX:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

Consulte Como converto a hora local para UTC no Python? Se o banco de dados tz estiver disponível em uma determinada plataforma; uma solução apenas para stdlib pode funcionar .

Siga os links se precisar de soluções para <3.3versões do Python.

jfs
fonte
1

Eu tentei o calendar.timegm da biblioteca padrão e funciona muito bem:

# convert a datetime to milliseconds since Epoch
def datetime_to_utc_milliseconds(aDateTime):
    return int(calendar.timegm(aDateTime.timetuple())*1000)

Ref: https://docs.python.org/2/library/calendar.html#calendar.timegm

Shaohong Li
fonte
retira frações de segundo. Assume que aDateTimeé uma hora UTC
jfs