Converti python datetime in epoca con strftime


209

Ho un tempo in UTC da cui desidero il numero di secondi dall'epoca.

Sto usando strftime per convertirlo nel numero di secondi. Prendendo come esempio il 1 ° aprile 2012.

>>>datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

Il 1 ° aprile 2012 UTC dell'epoca è 1333238400 ma questo sopra restituisce 1333234800 che è diverso di 1 ora.

Quindi sembra che Strftime stia prendendo in considerazione il tempo del mio sistema e applichi un fuso orario da qualche parte. Pensavo che il datetime fosse puramente ingenuo?

Come posso aggirarlo? Se possibile, evitare di importare altre librerie se non standard. (Ho problemi di portabilità).



11
Sono l'unico a notare che usi numeri ottali nei numeri?
Fish Monitor


3
La versione più recente di Python 3.3+ hadatetime.datetime.timestamp(datetime.datetime.utcnow())
MarkHu,

Risposte:


390

Se vuoi convertire un datetime di Python in secondi dall'epoca puoi farlo esplicitamente:

>>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds()
1333238400.0

In Python 3.3+ puoi timestamp()invece usare :

>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0

Perché non dovresti usare datetime.strftime('%s')

Python in realtà non supporta% s come argomento per strftime (se si controlla su http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior non è nell'elenco), l'unico la ragione per cui funziona è perché Python sta trasmettendo le informazioni all'ora di punta del sistema, che utilizza il fuso orario locale.

>>> datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

7
Sono impazzito cercando di capire perché vedo molto tempo prima ("% s"), ma non è nei documenti. Grazie per niente questo!
Jonathan Vanasco,

54
non usare .strftime("%s"): non è supportato, non è portatile, può produrre silenziosamente un risultato errato per un oggetto datetime consapevole, non riesce se l'input è in UTC (come nella domanda) ma il fuso orario locale non è UTC
jfs

2
@earthmeLon Il bracketing è errato. I timedeltas (creati sottraendo due intervalli di dati) hanno total_seconds, ma i periodi di dati no.
jleahy,

2
Questo non funziona per me:AttributeError: 'datetime.timedelta' object has no attribute 'total_seconds'
Michael,

3
@Michael Quella funzione è nuova in Python 2.7, devi usare una versione precedente. Per le versioni precedenti alla 2.7 puoi farlo td.seconds + td.days*24*3600. Questo scarta la parte dei microsecondi.
jleahy,

100

Ho avuto seri problemi con fusi orari e simili. Il modo in cui Python gestisce tutto ciò che sembra essere piuttosto confuso (per me). Le cose sembrano funzionare bene usando il modulo calendario (vedi link 1 , 2 , 3 e 4 ).

>>> import datetime
>>> import calendar
>>> aprilFirst=datetime.datetime(2012, 04, 01, 0, 0)
>>> calendar.timegm(aprilFirst.timetuple())
1333238400

7
+1 perché è l'unica risposta che funziona per l'input nella domanda.
jfs

è portatile?
Benjaminz,

1
Questa dovrebbe essere contrassegnata come la risposta giusta, poiché risponde alla preoccupazione in questione. vnice kudos
Leo Prince,

2
Questo funziona, ma nota la domanda dichiarata: "Ho un orario in UTC" Questo metodo utilizzerà sempre il fuso orario locale del sistema. Non è possibile specificare un fuso orario. Se aprilFirstin questo esempio fosse un'istanza "consapevole" e utilizzasse un fuso orario diverso dal fuso orario del sistema, il risultato non sarebbe corretto (il fuso orario si perde nella timetuple()chiamata). Per ottenere la risposta giusta per un datetime "consapevole", è possibile utilizzare awaredt.timestamp()il recente Python 3. Per Python 2 è più difficile; un modo è usare la arrowlibreria. arrow.get(awaredt).timestampcapirà bene.
Adam Williamson

1
Buon punto, @AdamWilliamson, ma il codice nell'esempio non sta localizzando l' datetimeoggetto, quindi ho pensato che "I have a time in UTC" significava che l'OP aveva un datetimeoggetto inconsapevole che si presumeva fosse in UTC per il quale voleva ottenere un epoch(se il datetimecaso fosse consapevole di TZ questo potrebbe, in effetti, cambiare le cose). Inoltre, tieni presente che questa risposta ha quasi 8 anni e molte cose sono successe da allora (è arrowstato rilasciato nel 2013, ad esempio)
BorrajaX

35
import time
from datetime import datetime
now = datetime.now()

time.mktime(now.timetuple())

1
è un modo errato di scrivere time.time()( mktime()potrebbe non riuscire durante le transizioni dell'ora legale mentre time.time()continua a funzionare). E non risponde alla domanda a meno che il fuso orario locale sia UTC (l'input nella domanda è in UTC). Anche se l'input rappresentasse un'ora locale, allora mktime()potrebbe anche fallire per date passate / future se non utilizza il database tz e se il fuso orario locale potrebbe avere offset dell'utility diversi negli anni, ad esempio Europa / Mosca nel 2010-2015 - - usa invece l'ora UTC (come nella domanda) o gli oggetti datetime sensibili al fuso orario.
jfs,

qui ci sono altri problemi con la conversione di un'ora locale (come restituita da .now()) in data / ora (restituita da mktime()) . Se lo leggi; capisci perché l'input UTC (usato nella domanda) è (molto) più preferibile di un oggetto datetime ingenuo che rappresenta l'ora locale
jfs

14
import time
from datetime import datetime
now = datetime.now()

# same as above except keeps microseconds
time.mktime(now.timetuple()) + now.microsecond * 1e-6

(Mi dispiace, non mi lascia commentare la risposta esistente)


Questo perché time.mktime non prende in considerazione la parte dei microsecondi, giusto?
Eduardo,

1
Corretta. La struttura della tupla temporale (basata sul puntone C) non ha uno spazio per i microsecondi, quindi dobbiamo prendere le informazioni dall'oggetto datetime e aggiungerle alla fine.
Charles Plager,


Sulle mie macchine, questo funziona correttamente anche se il mio fuso orario è ET.
Charles Plager,

1
Questo ti darà diversi timestamp su sistemi diversi in base all'ora locale del sistema.
Yousaf

6

se hai solo bisogno di un timestamp in unix / epoch time, questa riga funziona:

created_timestamp = int((datetime.datetime.now() - datetime.datetime(1970,1,1)).total_seconds())
>>> created_timestamp
1522942073L

e dipende solo dalle datetime opere in python2 e python3


3

Funziona in Python 2 e 3:

>>> import time
>>> import calendar
>>> calendar.timegm(time.gmtime())
1504917998

Solo seguendo i documenti ufficiali ... https://docs.python.org/2/library/time.html#module-time


1) Ciò presuppone che tu voglia convertire adesso, non un oggetto datetime casuale. 2) Non hai bisogno del calendario. time.mktime (randomDateTime.timetuple ()) + randomDateTime.microsecond * 1e-6
Charles Plager

@CharlesPlager time.mktime non è corretto; interpreta l'argomento nel fuso orario locale, mentre l'OP vuole il tempo interpretato in UTC (come fa calendar.timegm).
Stewbasic,

Questa è la risposta più accurata per me, se stai cercando di convertire il tuo tempo in GMT e vuoi mantenerlo così nella conversione in data e ora.
Yousaf

Basta seguire la tua risposta, calendar.timegm (datetime.strptime ("2019-05-03T05: 40: 09.770494 + 00: 00" [: 16], '% Y-% m-% dT% H:% M'). timetuple ()) Ho il timestamp in utc e non importa quale sistema tu usi, mi dà il timestamp corretto, il trucco è usare strptime.timetumple
Yousaf

2

Per una soluzione esplicita indipendente dal fuso orario, utilizzare la libreria pytz.

import datetime
import pytz

pytz.utc.localize(datetime.datetime(2012,4,1,0,0), is_dst=False).timestamp()

Uscita (float): 1333238400.0


ho visto una risposta simile su stackoverflow.com/a/21145908/4355695 , ma questa come linea singola è ottima per il mio caso d'uso in cui i dati in arrivo sono in UTC e solo .timestamp () stava assumendo che fossero in ora locale .
Nikhil VJ,

Questo funziona per date inferiori al 1970. Grazie. La risposta accettata non funziona per date inferiori a 1970. (Python 3.7.3 64-bit Anaconda3)
canbax

-1

In Python 3.7

Restituisce un datetime corrispondente a un date_string in uno dei formati emessi da date.isoformat () e datetime.isoformat (). In particolare, questa funzione supporta stringhe nel formato (i) AAAA-MM-GG [* HH [: MM [: SS [.fff [fff]]]] [+ HH: MM [: SS [.ffffff]]]] , dove * può corrispondere a qualsiasi singolo carattere.

https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat


1
Ricorda che questo è stato introdotto in Python 3.7.
keithpjolley
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.