Ho dt = datetime(2013,9,1,11)
, e vorrei ottenere un timestamp Unix di questo oggetto datetime.
Quando faccio (dt - datetime(1970,1,1)).total_seconds()
ho ottenuto il timestamp 1378033200
.
Quando lo riconverto usando datetime.fromtimestamp
ho ottenuto datetime.datetime(2013, 9, 1, 6, 0)
.
L'ora non corrisponde. Cosa mi sono perso qui?
Quello che ti sei perso qui sono i fusi orari.
Presumibilmente hai cinque ore fuori UTC, quindi 2013-09-01T11:00:00 locale e 2013-09-01T06:00:00Z sono la stessa ora.
Devi leggere la parte superiore della documentazione di datetime
, che spiega i fusi orari e gli oggetti "naive" e "aware".
Se il tuo naive datetime originale era UTC, il modo per recuperarlo è usare utcfromtimestamp
invece di fromtimestamp
.
D'altra parte, se il vostro datetime originale ingenuo era locale, non avreste dovuto sottrarre un timestamp UTC da esso in primo luogo; usate invece datetime.fromtimestamp(0)
.
Oppure, se avevi un oggetto datetime consapevole, devi usare una data locale (consapevole) su entrambi i lati, o convertire esplicitamente da e verso UTC.
Se avete, o potete aggiornare a Python 3.3 o successivo, potete evitare tutti questi problemi usando semplicemente il metodo timestamp
invece di cercare di capire come farlo da soli. E anche se non ce l'avete, potreste considerare di prendere in prestito il suo codice sorgente.
(E se potete aspettare Python 3.4, sembra che PEP 341 sia probabile che entri nella versione finale, il che significa che tutte le cose di cui parlavamo io e J.F. Sebastian nei commenti dovrebbero essere fattibili solo con la stdlib, e funzionare allo stesso modo sia su Unix che su Windows).
Piuttosto che questa espressione per creare un timestamp POSIX da dt
,
(dt - datetime(1970,1,1)).total_seconds()
Usa questo:
int(dt.strftime("%s"))
Ottengo la risposta giusta nel tuo esempio usando il secondo metodo.
EDIT: un po' di follow-up... Dopo alcuni commenti (vedi sotto), ero curioso della mancanza di supporto o documentazione per %s
in strftime
. Ecco cosa ho trovato:
Nel sorgente Python per datetime
e time
, la stringa STRFTIME_FORMAT_CODES
ci dice:
"Other codes may be available on your platform.
See documentation for the C library strftime function."
Quindi ora se noi man strftime
(su sistemi BSD come Mac OS X), troverete il supporto per %s
:
"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."
Comunque, questo è il motivo per cui %s
funziona sui sistemi in cui funziona. Ma ci sono soluzioni migliori per il problema di OP (che tengono conto dei fusi orari). Vedi la risposta accettata di @abarnert qui.
Beh, quando si converte in timestamp unix, python assume fondamentalmente UTC, ma mentre si converte indietro vi darà una data convertita al vostro fuso orario locale.
Vedi questa domanda/risposta; https://stackoverflow.com/questions/18812638/get-timezone-used-by-datetime-datetime-fromtimestamp