Convierta un tiempo de unix a un objeto de fecha y hora y vuelva (par de funciones de conversión de tiempo que son inversas)

Estoy intentando escribir un par de funciones, dt y ut , que se convierten de un lado a otro entre el tiempo normal de Unix (segundos desde 1970-01-01 00:00:00 UTC) y un objeto datetime de Python.

Si dt y ut fueran inversos adecuados, este código imprimiría la misma marca de tiempo dos veces:

 import time, datetime # Convert a unix time u to a datetime object d, and vice versa def dt(u): return datetime.datetime.fromtimestamp(u) def ut(d): return time.mktime(d.timetuple()) u = 1004260000 print u, "-->", ut(dt(u)) 

Por desgracia, la segunda marca de tiempo es 3600 segundos (una hora) menos que la primera. Creo que esto solo ocurre con tiempos de unix muy particulares, tal vez durante esa hora se salte el horario de verano. Pero, ¿hay una manera de escribir dt y ut para que sean verdaderos inversos entre sí?

Pregunta relacionada: Hacer matplotlib’s date2num y num2date perfect inverses

Tienes razón en que este comportamiento está relacionado con el horario de verano. La forma más fácil de evitar esto es asegurarse de usar una zona horaria sin horario de verano, UTC tiene más sentido aquí.

datetime.datetime.utcfromtimestamp() y calendar.timegm() tratan con tiempos UTC, y son inversos exactos.

 import calendar, datetime # Convert a unix time u to a datetime object d, and vice versa def dt(u): return datetime.datetime.utcfromtimestamp(u) def ut(d): return calendar.timegm(d.timetuple()) 

Aquí hay un poco de explicación detrás de por qué datetime.datetime.fromtimestamp() tiene un problema con el horario de verano, desde los documentos:

Devuelve la fecha y hora locales correspondientes a la marca de hora POSIX, como la que devuelve time.time() . Si el argumento opcional tz es Ninguno o no está especificado, la marca de tiempo se convierte a la fecha y hora locales de la plataforma, y ​​el objeto de fecha y hora devuelto es ingenuo.

La parte importante aquí es que obtiene un objeto de datetime.datetime ingenuo, lo que significa que no hay información de zona horaria (o de horario de verano) como parte del objeto. Esto significa que varias marcas de tiempo distintas se pueden asignar al mismo objeto datetime.datetime cuando se usa fromtimestamp() , si se fromtimestamp() a elegir los tiempos que caen durante el retroceso del horario de verano:

 >>> datetime.datetime.fromtimestamp(1004260000) datetime.datetime(2001, 10, 28, 1, 6, 40) >>> datetime.datetime.fromtimestamp(1004256400) datetime.datetime(2001, 10, 28, 1, 6, 40)