2012-03-28 27 views
6

Estoy usando datetime.fromtimestamp para convertir el tiempo de época en hora local. Descubrí que datetime.fromtimestamp hace un salto discreto de una hora en un determinado momento y estoy completamente desconcertado sobre por qué lo hace.`fromtimestamp` de Python hace un salto discreto

(También estoy usando time.mktime para convertir un objeto de fecha y hora en el tiempo época, as suggested by Raymond Hettinger. No estoy seguro de si se trata de información relevante para esta pregunta, por lo que estoy diciendo esto por si acaso.)

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

Escoger un tiempo de época específica:

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

la conversión a una fecha y hora utilizando fromtimestamp:

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

Tenemos un tiempo de 3 am.

Ahora vamos a convertir el tiempo que es exactamente un segundo antes de que:

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

repente Obtenemos 1:59 am!

¿Qué pasó? Sé que cosas así ocurren alrededor de los días bisiestos, pero ¿desde cuándo es el 30 de marzo un día bisiesto?

Debo señalar que esto me ha sucedido solo en Linux y no en Windows. Y creo que las diferentes computadoras Linux (en diferentes zonas horarias) tienen un punto de tiempo diferente en el que fromtimestamp hace el salto.

Respuesta

4

Fácil. El 30 de marzo es presumiblemente un interruptor de horario de verano en su zona horaria.

Así que en ese día, hora, efectivamente, ir 1:59:59-3:00:00

+0

Ya veo. Entonces 'fromtimestamp' es consciente de la zona horaria en la que vivo y sabe qué horas omitir. Pero los objetos 'datetime' no son conscientes de este salto: si restamos el objeto' datetime' a las 3 a.m. del de las 2 a.m., obtengo un 'timedelta' de una hora, donde debería estar obteniendo cero. –

+0

¿Cómo, entonces, hago que los objetos 'datetime' conozcan mi zona horaria, y les hago usar * exact * alguna zona horaria como' fromtimestamp', para que estén completamente sincronizados? –

+0

@RamRachum Pase el indicador 'tzinfo' al construir la marca de tiempo. la biblioteca 'pytz' puede ser de alguna ayuda con eso. – Amber

7

fromtimestamp utiliza "ambiente local" del usuario actual, según la definición de la biblioteca POSIX C (ver man (3) tzset, y documentos del módulo time).

Si realmente desea obtener una representación pytz de la hora local del entorno del usuario actual, el paquete datetime-tz tiene una función para autodetectarlo.

Sin embargo, la sabiduría común es trabajar siempre con UTC, y evitar todos los problemas de horario de verano (usar la zona horaria local solo para la visualización final). Utilice datetime.fromtimestamp(x, tz=pytz.UTC), o, si usted no tiene 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. También puede establecer la configuración regional de su proceso en UTC (pero esto podría no funcionar en sistemas operativos que no sean POSIX):

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

+1 Un gran consejo. –

Cuestiones relacionadas