In Python, come si converte un oggetto `datetime` in secondi?


226

Mi scuso per la semplice domanda ... Sono nuovo di Python ... Ho cercato in giro e nulla sembra funzionare.

Ho un sacco di oggetti datetime e voglio calcolare il numero di secondi da un tempo fisso in passato per ognuno (ad esempio dal 1 ° gennaio 1970).

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

Questo sembra differenziare solo le date che hanno giorni diversi:

t.toordinal()

Ogni aiuto è molto apprezzato.



2
Probabilmente convertirò entrambi in S sin dall'epoca e andrei da lì: int(t.timestamp())
nerdwaller il

Risposte:


233

Per la data speciale del 1 gennaio 1970 ci sono più opzioni.

Per qualsiasi altra data di inizio è necessario ottenere la differenza tra le due date in secondi. Sottraendo due date si ottiene atimedelta oggetto che a partire da Python 2.7 ha una total_seconds()funzione.

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

La data di inizio è di solito specificata in UTC, quindi per risultati corretti il datetime feed in questa formula dovrebbe essere anche in UTC. Se datetimenon sei già in UTC, dovrai convertirlo prima di utilizzarlo o collegare una tzinfoclasse che ha l'offset corretto.

Come notato nei commenti, se ne hai uno tzinfoallegato, datetimene avrai bisogno anche uno alla data di inizio o la sottrazione fallirà; per l'esempio sopra aggiungerei tzinfo=pytz.utcse si utilizza Python 2 o tzinfo=timezone.utcse si utilizza Python 3.


1
Python ora mi avverte: "TypeError: impossibile sottrarre i tempi dei dati offset-ingenuo e con rilevamento offset" Qual è la soluzione migliore per risolvere il problema?
Aaron Ash,

2
@Charybdis, prova datetime.datetime(1970,1,1,tzinfo=pytz.utc).
Mark Ransom,

9
Prendi in considerazione l'uso: l' datetime.datetime.utcfromtimestamp(0) ho usato per ottenere facilmente l '"epoca". Si noti che l'epoca non è sempre la stessa su tutti i sistemi.
DA

3
Fai molta attenzione con i fusi orari qui. Sono a UTC + 2, il che significa che l'output di time.time()e datetime.now() - datetime(1970, 1, 1)differisce di 7200 secondi. Piuttosto usare (t - datetime.datetime.fromtimestamp(0)).total_seconds(). Evitare Non utilizzare utcfromtimestamp(0)se si desidera convertire un datetime nel fuso orario locale.
Carl

2
@DA: Python non supporta epoche non POSIX . Tutti i sistemi in cui Python funziona utilizzano la stessa epoca: 1970-01-01 00:00:00 UTC
jfs

130

Per ottenere il tempo Unix (secondi dal 1 ° gennaio 1970):

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

22
fai attenzione quando usi time.mktime perché è espresso dall'ora locale e dipende dalla piattaforma
Shih-Wen Su

7
Stai davvero attento. Mi ha morso il culo alla grande
Arg

presuppone che tsia l'ora locale. L'offset UTC per il fuso orario locale potrebbe essere stato diverso in passato e se mktime()(libreria C) non ha accesso ai dati di un fuso orario storico su una determinata piattaforma di quanto potrebbe non funzionare ( pytzè un modo portatile per accedere al database tz). Inoltre, l'ora locale può essere ambigua, ad esempio durante le transizioni dell'ora legale - per disambiguare è necessario disporre di informazioni aggiuntive, ad esempio, se si sa che i valori di data / ora consecutivi dovrebbero aumentare in un file di registro
jfs

1
Fai attenzione quando lo usi con tempi che hanno frazioni di secondo. time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())provoca 1564819506.0, facendo cadere silenziosamente i millisecondi, ma datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(risposta di Andrzej pronobis) risulta 1564819506.912, il risultato atteso.
Alex

128

A partire da Python 3.3 questo diventa super facile con il datetime.timestamp()metodo. Questo ovviamente sarà utile solo se hai bisogno del numero di secondi dal 1970-01-01 UTC.

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

Il valore restituito sarà un float che rappresenta anche le frazioni di secondo. Se il datetime è un fuso orario ingenuo (come nell'esempio sopra), si supporrà che l'oggetto datetime rappresenti l'ora locale, ovvero sarà il numero di secondi dall'ora corrente nella propria posizione al 1970-01-01 UTC.


3
Chiunque abbia votato in negativo, potrebbe spiegare perché?
Andrzej Pronobis,

5
Suppongo che il downvote sia dovuto al tag python-2.7 sulla domanda (è solo un'ipotesi).
jfs,

3
Questa dovrebbe essere la risposta accettata / la risposta accettata dovrebbe essere aggiornata di conseguenza.
DreamFlasher,

11
È ora di aggiornare immagino;)
DreamFlasher il

è possibile calcolare questa distanza da un'altra data di inizio? (intendo per cambiare la data 1970-01-01)
pellerossa Pelles

29

Forse fuori tema: per ottenere il tempo UNIX / POSIX dal datetime e riconvertirlo:

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

Nota che diversi fusi orari hanno un impatto sui risultati, ad esempio i miei ritorni TZ / DST attuali:

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

pertanto si dovrebbe considerare la normalizzazione a UTC utilizzando le versioni UTC delle funzioni.

Si noti che il risultato precedente può essere utilizzato per calcolare l'offset UTC del fuso orario corrente. In questo esempio questo è + 1h, ovvero UTC + 0100.

Riferimenti:


mktime()potrebbe fallire . In generale, è necessario pytzconvertire l'ora locale in utc, per ottenere il timestamp POSIX.
jfs,

calendar.timegm () sembra essere la versione utc di time.mktime ()
frankster

27

int (t.strftime("%s")) funziona anche


1
Funziona per me in Python 2.7, con import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(come specificato da OP). Ma davvero, dubito che% s sia un formato orario aggiunto di recente.
dan3,

1
@ dan3: sbagliato. %snon è supportato (potrebbe funzionare su alcune piattaforme se tè un oggetto datetime ingenuo che rappresenta l'ora locale e se la libreria C locale ha accesso al database tz, altrimenti il ​​risultato potrebbe essere errato). Non usarlo.
jfs,

%snon è documentato da nessuna parte. Lo scrivo in codice reale e mi chiedevo cosa fosse questo e guardo nella documentazione e non esiste %s. C'è solo con la grande S solo per i secondi.
VStoykov,

13

dai documenti di Python:

timedelta.total_seconds()

Restituisce il numero totale di secondi contenuto nella durata. Equivalente a

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

calcolato con vera divisione abilitata.

Si noti che per intervalli di tempo molto grandi (superiori a 270 anni sulla maggior parte delle piattaforme) questo metodo perderà la precisione dei microsecondi.

Questa funzionalità è nuova nella versione 2.7.


1
c'è un piccolo problema con il calcolo che deve essere 10 6 invece di 10 * 6 ... td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 6) / 10 ** 6
sdu

@sdu great catch - il doppio asterisco è nella mia risposta, ma StackOverflow lo consuma, tenta di rettificare solo incoraggiare il testo.
Michael,

2

Per convertire un oggetto datetime che rappresenta l'ora in UTC in data / ora POSIX :

from datetime import timezone

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

Per convertire un oggetto datetime che rappresenta l'ora nel fuso orario locale in data / ora POSIX:

import tzlocal # $ pip install tzlocal

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

Vedi Come posso convertire l'ora locale in UTC in Python? Se il database tz è disponibile su una determinata piattaforma; una soluzione solo stdlib può funzionare .

Segui i collegamenti se hai bisogno di soluzioni per le <3.3versioni di Python.


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.