Como converter um objeto datetime em milissegundos desde a época (hora unix) no Python?

354

Eu tenho um datetimeobjeto Python que desejo converter em tempo unix ou segundos / milissegundos desde a época de 1970.

Como eu faço isso?

SuperString
fonte
Se você chegou aqui apenas querendo segundos da época atual com precisão de milissegundos, tente o $ python -c 'import time; print(time.time())'que deu:1584487455.698623
MarkHu

Respostas:

473

Parece-me que a maneira mais simples de fazer isso é

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0
Sophie Alpert
fonte
32
Até agora, esta é a melhor solução (se a versão python for> 2.7). Porque a implementação de %sé dependente do SO! Portanto, qualquer pessoa deseja que o código funcione de forma confiável, independentemente de qual SO, NUNCA deve usar %s. Para 2,3 <py ver <2,7. Um pode simplesmente construir um total_seconds()como este:delta.days*86400+delta.seconds+delta.microseconds/1e6
Wang
14
nota: dtdeve estar no UTC (não local). Veja resposta semelhante com o suporte ao Python 2.6 / 3
jfs 28/10/12
7
Vale ressaltar que, se tudo o que você deseja é um carimbo de data / hora unix verdadeiro, conforme definido aqui en.wikipedia.org/wiki/Unix_time (e assim, você usará apenas a função unix_time nesta resposta), você deve delta.total_seconds () com int evitar acabar com uma bóia
corford
11
época calculada usando utcfromtimestamp(0)pode causar apenas se 'tz' 'tz' compensar não é 0. Isso ocorre porque dt no dt- epochtem 'tz' calculado nele onde, como época é UTC tempo. A melhor maneira de calcular a época é epoch = datetime.datetime(1970, 1, 1)onde o fuso horário está em consideração.
ahj 6/01/16
35
Por que oh, por que datetime.utcfromtimestamp(0)retornar um datetime sem tzinfo? Está bem ali no nome do método, utc fromtimestamp. Para torná-lo não ingênuo, tenho que fazer algo parecido datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Isto é necessário se dté fuso horário consciente ou então você vai terTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg
170

No Python 3.3, foi adicionado um novo método timestamp:

import datetime
seconds_since_epoch = datetime.datetime.now().timestamp()

Sua pergunta afirmou que você precisava de milissegundos, que você pode obter assim:

milliseconds_since_epoch = datetime.datetime.now().timestamp() * 1000

Se você usar timestampum objeto de data e hora ingênuo, será assumido que ele está no fuso horário local. Use objetos de data e hora com reconhecimento de fuso horário se não for o que você pretende que isso aconteça.

eshizhan
fonte
28
Nota: o .timestamp()método supõe que um horário de entrada de entrada ingênuo esteja no fuso horário local (e o horário local pode ser ambíguo). Se ele estiver em UTC, em seguida, usar dt.replace(tzinfo=timezone.utc).timestamp()vez .
JFS
11
datetime.timestamp () retorna a época segundos como um ponto flutuante. Para obter milisegundos: int (datetime.timestamp () * 1000)
Solar.gy
9
Esta resposta não é um exemplo de cópia e cola, no espírito dos documentos não humanos em docs.python.org/3/library/… - e é: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu
3
Em 3.6 (pelo menos), datetime.timestamp () assume que um fuso horário ingênuo (tzinfo = None) está no UTC. Então sempre melhor ter o seu conjunto de fuso horário: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()mas não (sempre) igual datetime.datetime.now().timestamp()(somente este último é igual ao resto, se o tz local é UTC ...)
Bluu
11
Para seu interesse, o inverso é] fromtimestamp( docs.python.org/3/library/… )
Flimm
98
>>> import datetime
>>> # replace datetime.datetime.now() with your datetime object
>>> int(datetime.datetime.now().strftime("%s")) * 1000 
1312908481000

Ou a ajuda do módulo de hora (e sem formatação de data):

>>> import datetime, time
>>> # replace datetime.datetime.now() with your datetime object
>>> time.mktime(datetime.datetime.now().timetuple()) * 1000
1312908681000.0

Respondida com ajuda de: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Documentação:

miku
fonte
6
Btw, strftime ("% s") retorna uma string vazia para mim. A segunda maneira funciona bem.
Pavel Vlasov
23
Só tem a segunda precisão
shuckc
6
'% s' não é suportado pelo Python, por exemplo, pode estar ausente no Windows. .timetuple()retorna tm_isdst=-1força mktime()a adivinhar. Pode adivinhar errado durante o horário de verão (50% de chance de erro +/- hora). Ambos '% s' e mktime()podem usar o deslocamento incorreto do utc para datas do passado. Você precisa de um fuso horário histórica db, como fornecido pelo pytzmódulo para converter de forma confiável hora local para POSIX timestamp (a menos OS já provê um db)
jfs
11
time.mktime(ts.timetuple())onde ts é de python datetime objeto
suhailvs
11
@suhail: leia meu comentário acima sobre mktime/timetuple. Também timetuple()retira frações de segundo e o objetivo da pergunta é obter o registro de data e hora com precisão de milissegundos.
JFS
13

É assim que eu faço:

from datetime import datetime
from time import mktime

dt = datetime.now()
sec_since_epoch = mktime(dt.timetuple()) + dt.microsecond/1000000.0

millis_since_epoch = sec_since_epoch * 1000
estani
fonte
2
@JFSebastian Obrigado pela atenção! de fato, não há dst sendo considerado. Se o seu servidor estiver no horário local em vez do UTC, isso fará a diferença. Ainda não encontrei nenhum motivo convincente para configurar servidores em algo que não seja o UTC. Minha moto é "escreva UTC, leia a hora local" para que você saiba sempre onde fica ...
estani
2
Você sempre pode usar calendar.timegm em vez de mktime para evitar o problema do mktime tentando adivinhar o fuso horário.
Decko
13

Recomendações dos documentos do Python 2.7 para otime módulo

Convertendo entre representações de tempo

Ankur Agarwal
fonte
@ChristopherBull basta dividir o número de milissegundos em 1000 para chegar a segundos
Jonas
5
Você entendeu mal e entendeu errado. Segundos estão prontos disponíveis nas funções acima. Você pode convertê-lo em milissegundos, mas seria a precisão de um segundo.
Christopher Bull
11
Essa resposta usa o timemódulo, mas o OP perguntou sobre o datetimemódulo. FWIW, a época atual mais simples éint(time.time())
MarkHu 01/02/19
7
from datetime import datetime
from calendar import timegm

# Note: if you pass in a naive dttm object it's assumed to already be in UTC
def unix_time(dttm=None):
    if dttm is None:
       dttm = datetime.utcnow()

    return timegm(dttm.utctimetuple())

print "Unix time now: %d" % unix_time()
print "Unix timestamp from an existing dttm: %d" % unix_time(datetime(2014, 12, 30, 12, 0))
Corford
fonte
timegm()funciona apenas com utc time. Ele não usa, tm_isdstportanto, você poderia usar em utcnow.timetuple()vez de utcnow.utctimetuple(). Nota: o uso naive_local_datetime.utctimetuple()estaria errado aqui. Não traduz a hora local para utc. timetuple()Chame também tiras de frações de segundo do resultado (se isso depende ou não da aplicação). Também a pergunta é sobre * milli * segundos, não segundos
jfs 15/05
Prefiro usar utcnow () e utctimetuple () para tornar o código absolutamente claro de que você está lidando com o UTC (e dessa forma, qualquer pessoa que o leia não precisará se lembrar que o timegm é apenas o UTC). utctimetuple () não implica tradução em um objeto dttm ingênuo (portanto, inicie o dttm com utcnow ()). Além disso, a pergunta mencionou segundos ou milissegundos.
corford
Nota: deveria ter dito no último comentário que li a pergunta como implicando que ele queria segundos ou milissegundos (provavelmente meu erro). Por milésimos, basta multiplicar por 1000 (como a resposta da pontuação mais alta sugere).
corford
utctimetuple()retira frações de segundo. Multiplicar por 1000não os recuperará.
JFS
11
Devido à maneira como o OP fez essa pergunta, não está claro exatamente o que ele / ela queria (ou seja, um verdadeiro timestamp unix ou um timestamp com precisão de milissegundos). Independentemente disso, ambas as perguntas já foram feitas e respondidas em outros lugares. Dito isto, acho que as respostas aqui são as mais rápidas e limpas para as pessoas se divertirem e fazerem um bom trabalho ilustrando as várias soluções para o problema.
corford
3
>>> import datetime
>>> import time
>>> import calendar

>>> #your datetime object
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 3, 19, 13, 0, 9, 351812)

>>> #use datetime module's timetuple method to get a `time.struct_time` object.[1]
>>> tt = datetime.datetime.timetuple(now)
>>> tt
time.struct_time(tm_year=2013, tm_mon=3, tm_mday=19, tm_hour=13, tm_min=0, tm_sec=9,     tm_wday=1, tm_yday=78, tm_isdst=-1)

>>> #If your datetime object is in utc you do this way. [2](see the first table on docs)
>>> sec_epoch_utc = calendar.timegm(tt) * 1000
>>> sec_epoch_utc
1363698009

>>> #If your datetime object is in local timeformat you do this way
>>> sec_epoch_loc = time.mktime(tt) * 1000
>>> sec_epoch_loc
1363678209.0

[1] http://docs.python.org/2/library/datetime.html#datetime.date.timetuple

[2] http://docs.python.org/2/library/time.html

Jinesh
fonte
3

Aqui está outra forma de solução com a normalização do seu objeto de tempo:

def to_unix_time(timestamp):
    epoch = datetime.datetime.utcfromtimestamp(0) # start of epoch time
    my_time = datetime.datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S.%f") # plugin your time object
    delta = my_time - epoch
    return delta.total_seconds() * 1000.0
arhoskins
fonte
2

Um pouco de código de pandas:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)
volhv
fonte
1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000
MattoTodd
fonte
9
Isto está errado! O cronograma não inclui milissegundos, portanto, o mktime não retornará a época com resolução em milissegundos. É inútil neste caso.
24712 Wang
@ Wang - você está correto, senhor, isso não retorna milis, apenas segundos
MattoTodd
11
Se você remover * 1000, no entanto, você obtémseconds_since_epoch . Promovendo esta resposta porque não me importo com milissegundos no momento.
precisa
0

Aqui está uma função que eu fiz com base na resposta acima

def getDateToEpoch(myDateTime):
    res = (datetime.datetime(myDateTime.year,myDateTime.month,myDateTime.day,myDateTime.hour,myDateTime.minute,myDateTime.second) - datetime.datetime(1970,1,1)).total_seconds()
    return res

Você pode agrupar o valor retornado assim: str (int (res)) Para retorná-lo sem um valor decimal para ser usado como string ou apenas int (sem o str)

Gil Allen
fonte
-14

Esta outra solução para datetime secreto para unixtimestampmillis.

private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static long GetCurrentUnixTimestampMillis()
    {
        DateTime localDateTime, univDateTime;
        localDateTime = DateTime.Now;          
        univDateTime = localDateTime.ToUniversalTime();
        return (long)(univDateTime - UnixEpoch).TotalMilliseconds;
    } 
samsanthosh2008
fonte
2
A pergunta é sobre a linguagem Python
Stéphane