Come posso convertire un oggetto datetime in millisecondi dall'epoca (tempo unix) in Python?


354

Ho un datetimeoggetto Python che voglio convertire in tempo unix, o secondi / millisecondi dall'epoca del 1970.

Come faccio a fare questo?



Se sei atterrato qui solo volendo i secondi dell'epoca attuale con precisione in millisecondi, prova a $ python -c 'import time; print(time.time())'dare:1584487455.698623
MarkHu

Risposte:


473

Mi sembra che il modo più semplice per farlo sia

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0

32
Finora questa è la soluzione migliore (se versione di Python> 2.7). Perché l'implementazione %sdipende dal SO! Pertanto, chiunque desideri che il codice funzioni in modo affidabile, indipendentemente dal sistema operativo, non deve MAI utilizzare %s. Per 2.3 <py ver <2.7. Si può semplicemente costruire un total_seconds()simile:delta.days*86400+delta.seconds+delta.microseconds/1e6
Wang

14
nota: dtdeve essere in UTC (non locale). Vedi una risposta simile con il supporto Python 2.6 / 3
jfs,

7
Vale la pena ricordare che se tutto ciò che desideri è un vero timestamp unix come definito qui en.wikipedia.org/wiki/Unix_time (e quindi utilizzerai solo la funzione unix_time da questa risposta), dovresti racchiudere delta.total_seconds () con int a evitare di finire con un galleggiante
Corford il

1
l'epoca calcolata usando utcfromtimestamp(0)può causare uno scostamento 'tz' solo se 'tz' non è 0. Ciò è dovuto dt al fatto che in dt- epoch'tz' è calcolato in esso dove l'epoca è l'ora UTC. Il modo migliore per calcolare l'epoca è epoch = datetime.datetime(1970, 1, 1)dove viene considerato il fuso orario.
ahj,

35
Perché oh perché datetime.utcfromtimestamp(0)restituisce un datetime senza tzinfo? È proprio lì nel nome del metodo, utc fromtimestamp. Per renderlo non ingenuo, devo fare qualcosa del genere datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Ciò è necessario se dtsi TypeError: can't subtract offset-naive and offset-aware datetimes
conosce il

170

In Python 3.3, aggiunto un nuovo metodo timestamp:

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

La tua domanda affermava che avevi bisogno di millisecondi, che puoi ottenere in questo modo:

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

Se si utilizza timestampun oggetto datetime ingenuo, si presuppone che si trovi nel fuso orario locale. Utilizzare oggetti datetime che riconoscono il fuso orario se questo non è ciò che si intende accadere.


28
Nota: il .timestamp()metodo presuppone che un datetime di input ingenuo sia nel fuso orario locale (e che l'ora locale possa essere ambigua). Se è in UTC, utilizzare dt.replace(tzinfo=timezone.utc).timestamp()invece .
jfs,

11
datetime.timestamp () restituisce epoche secondi come float. Per ottenere millisecondi: int (datetime.timestamp () * 1000)
Solar.gy

9
Questa risposta non è un esempio copia-e-incollabile, nello spirito dei documenti non umani-friendly su docs.python.org/3/library/… --questo è: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu,

3
In 3.6 (almeno), datetime.timestamp () presuppone che un fuso orario ingenuo (tzinfo = None) sia in UTC. Quindi è sempre meglio avere il fuso orario impostato: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()ma non (sempre) uguale a datetime.datetime.now().timestamp()(quest'ultimo è uguale solo al resto se il tz locale è UTC ...)
Bluu,

1
Per il tuo interesse, il contrario è] 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

O l'aiuto del modulo orario (e senza formattazione della data):

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

Risposta con l'aiuto di: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Documentazione:


6
A proposito, strftime ("% s") restituisce una stringa vuota per me. Il secondo modo funziona bene.
Pavel Vlasov,

23
Ha solo una seconda precisione
shuckc il

6
'% s' non è supportato da Python, ad esempio, potrebbe essere assente su Windows. .timetuple()ritorna tm_isdst=-1costringe mktime()a indovinare. Potrebbe indovinare erroneamente durante l'ora legale (probabilità del 50% di errore +/- ora). Entrambi '% s' e mktime()possono utilizzare l'offset utc errato per le date del passato. È necessario un db di fuso orario storico come quello fornito dal pytzmodulo per convertire in modo affidabile l'ora locale in data / ora POSIX (a meno che il sistema operativo non fornisca già tale db)
jfs

1
time.mktime(ts.timetuple())dove ts è l'oggetto datetime di Python
suhailvs,

1
@suhail: leggi il mio commento sopra mktime/timetuple. timetuple()Elimina anche le frazioni di secondo e il punto della domanda è ottenere il timestamp con precisione in millisecondi.
jfs,


13

Ecco come lo faccio:

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


2
@JFSebastian Grazie per il testa a testa! in effetti non è stato preso in considerazione nessun caso. Se il tuo server è in ora locale invece di UTC, allora farà la differenza. Non ho trovato (ancora) alcun motivo convincente per impostare i server in qualcosa di diverso da UTC. La mia moto è "scrivi UTC, leggi l'ora locale" in modo da sapere sempre dove
alloggi

2
Puoi sempre usare calendar.timegm invece di mktime per evitare il problema di mktime che prova a indovinare il fuso orario.
Decko

13

@ChristopherBull Dividi il numero di millisecondi per 1000 per arrivare ai secondi
Jonas,

5
Hai frainteso e capito nel modo sbagliato. I secondi sono tutti disponibili nelle funzioni precedenti. Puoi convertirlo in millisecondi, ma sarebbe la precisione di un secondo.
Christopher Bull,

1
Questa risposta utilizza il timemodulo, ma l'OP ha chiesto del datetimemodulo. FWIW, l'epoca attuale più semplice èint(time.time())
MarkHu

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))

timegm()funziona solo con il tempo utc. Non utilizza tm_isdstquindi è possibile utilizzare utcnow.timetuple()invece di utcnow.utctimetuple(). Nota: l'utilizzo naive_local_datetime.utctimetuple()sarebbe sbagliato qui. Non traduce l'ora locale in utc. timetuple()Chiama anche le strisce di frazione di secondo dal risultato (se è importante dipende dall'applicazione). Anche la domanda pone circa * milli * secondi, non secondi
jfs

Preferisco usare utcnow () e utctimetuple () per rendere il codice assolutamente chiaro che hai a che fare con UTC (e in questo modo chiunque lo legga non deve ricordare che timegm è solo UTC). utctimetuple () non implica la traduzione su un oggetto dttm ingenuo (quindi iniziando il dttm con utcnow ()). Inoltre, domanda menzionata secondi o millisecondi.
Corford,

Nota: avrei dovuto dire nell'ultimo commento che ho letto la domanda come sottinteso che voleva secondi o millisecondi (probabilmente il mio errore). Per i millis, basta moltiplicare per 1000 (come suggerisce la risposta più alta del punteggio).
corford,

utctimetuple()toglie le frazioni di secondo. Moltiplicare per 1000non li ripristinerà.
jfs,

1
A causa del modo in cui il PO ha posto questa domanda, non è chiaro esattamente cosa desiderasse (cioè un vero timestamp unix o un timestamp con precisione millisecondo). Indipendentemente da ciò, entrambe le domande sono già state poste e hanno risposto altrove. Detto questo, penso che le risposte qui siano le più veloci e pulite per le persone che si lamentano e fanno un buon lavoro illustrando le varie soluzioni al 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


3

Ecco un'altra forma di soluzione con la normalizzazione dell'oggetto time:

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

2

Un po 'di codice panda:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)

1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000

9
Questo è sbagliato! L'orario non include i millisecondi, quindi mktime non restituirà l'epoca con una risoluzione di millisecondi. È inutile in questo caso.
Wang

@Wang - hai ragione signore, questo non restituisce millis, solo secondi
MattoTodd


1
Se rimuovi * 1000, però, ottieni seconds_since_epoch. Valorizzare questa risposta perché al momento non mi interessano i millisecondi.
Michael Scheper,

0

Ecco una funzione che ho creato sulla base della risposta sopra

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

Puoi racchiudere il valore restituito in questo modo: str (int (res)) Per restituirlo senza un valore decimale da usare come stringa o solo int (senza str)


-14

Quest'altra soluzione per convertire il datetime in 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;
    } 

2
La domanda riguarda il linguaggio Python
Stéphane,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.