2012-03-28 10 views
6

Sto usando datetime.fromtimestamp per convertire il tempo storico in ora locale. Ho trovato che datetime.fromtimestamp fa un salto discreto di un'ora ad un certo punto del tempo e sono completamente sconcertato sul perché lo faccia.Il `fromtimestamp` di Python esegue un salto discreto

(Sono anche utilizzando time.mktime per convertire un oggetto datetime nel tempo all'epoca, as suggested by Raymond Hettinger. Io non so se si tratta di informazioni rilevanti per questa domanda, quindi sto dicendo questo per ogni evenienza.)

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import time, datetime 
>>> def datetime_to_epoch_time(datetime_): 
...  return time.mktime(datetime_.timetuple()) + datetime_.microsecond/1e6 
... 

Scegliere un determinato tempo di un'epoca:

>>> x = datetime_to_epoch_time(datetime.datetime(2012, 3, 30, 3, 0)) 

convertirlo in un datetime utilizzando fromtimestamp:

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 

Abbiamo un orario di 3:00.

Ora cerchiamo di convertire il tempo che è esattamente un secondo prima che:

>>> datetime.datetime.fromtimestamp(x-1) 
datetime.datetime(2012, 3, 30, 1, 59, 59) 

Abbiamo improvvisamente otteniamo 01:59!

Cosa è successo? So che cose del genere succedono nei giorni bisestili, ma da quando è il 30 marzo un giorno bisestile?

Devo notare che questo mi è successo solo su Linux e non su Windows. E penso che diversi computer Linux (in diversi fusi orari) abbiano un diverso punto temporale in cui il salto è fromtimestamp.

risposta

4

Facile. Il 30 marzo è presumibilmente un interruttore dell'ora legale nel tuo fuso orario.

Quindi, in quel giorno, il tempo ha fatto davvero andare 1:59:59-03:00:00

+0

vedo. Quindi 'fromtimestamp' è a conoscenza del fuso orario in cui vivo e sa in quali ore saltare. Ma gli oggetti 'datetime' non sono consapevoli di questo salto: se sottrai l'oggetto' datetime' per 3am da quello per 2am, ottengo un 'timedelta' di un'ora, dove dovrei ottenere zero. –

+0

Come posso quindi rendere gli oggetti 'datetime' consapevoli del mio fuso orario e farli usare * esatto * un certo fuso orario come' fromtimestamp', in modo che siano completamente sincronizzati? –

+0

@RamRachum Passa il flag 'tzinfo' quando costruisci il timestamp. la libreria 'pytz' potrebbe essere di aiuto in questo. – Amber

7

fromtimestamp usa "ambiente locale" dell'utente corrente, come definito dalla libreria POSIX C (vedi man (3) tzset, e documenti del modulo time).

Se si desidera ottenere una rappresentazione pytz dell'ambiente locale dell'utente corrente, il pacchetto datetime-tz ha una funzione per il rilevamento automatico.

Tuttavia, la saggezza comune è di lavorare sempre con UTC ed evitare tutti i problemi relativi all'ora legale (utilizzare il fuso orario locale solo per la visualizzazione finale). Utilizzare datetime.fromtimestamp(x, tz=pytz.UTC), oppure, se non si dispone di pytz:

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 
>>> datetime.datetime.utcfromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
>>> datetime.datetime.utcfromtimestamp(x-1) 
datetime.datetime(2012, 3, 29, 23, 59, 59) 

P.S. È anche possibile impostare il processo di locale a UTC (ma questo potrebbe non funzionare su non-POSIX OS):

>>> import os,time 
>>> os.environ["TZ"] = "UTC" 
>>> time.tzset() 
>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
+0

+1 Ottimo consiglio. –

Problemi correlati