Tengo dt = datetime(2013,9,1,11)
, y me gustaría obtener una marca de tiempo Unix de este objeto datetime.
Cuando hago (dt - datetime(1970,1,1)).total_seconds()
obtengo el timestamp 1378033200
.
Al convertirlo de nuevo usando datetime.fromtimestamp
obtengo datetime.datetime(2013, 9, 1, 6, 0)
.
La hora no coincide. ¿Qué me he perdido aquí?
Lo que se ha perdido aquí son las zonas horarias.
Es de suponer que tienes cinco horas de diferencia con respecto a UTC, por lo que 2013-09-01T11:00:00 local y 2013-09-01T06:00:00Z son la misma hora.
Necesitas leer la parte superior de los documentos de datetime
, que explican las zonas horarias y los objetos "naive" y "aware".
Si tu fecha original era UTC, la forma de recuperarla es usar utcfromtimestamp
en lugar de fromtimestamp
.
Por otro lado, si su fecha original era local, no debería haber restado una marca de tiempo UTC en primer lugar; utilice datetime.fromtimestamp(0)
en su lugar.
O, si tienes un objeto datetime consciente, necesitas usar una época local (consciente) en ambos lados, o convertir explícitamente a y desde UTC.
Si tienes, o puedes actualizarte a Python 3.3 o posterior, puedes evitar todos estos problemas simplemente usando el método timestamp
en lugar de intentar averiguar cómo hacerlo tú mismo. E incluso si no lo haces, puedes considerar tomar prestado su código fuente.
(Y si puedes esperar a Python 3.4, parece que PEP 341 es probable que llegue a la versión final, lo que significa que todas las cosas de las que J.F. Sebastian y yo hablábamos en los comentarios deberían poder hacerse sólo con la stdlib, y funcionar de la misma manera tanto en Unix como en Windows).
En lugar de esta expresión para crear una marca de tiempo POSIX a partir de dt
,
(dt - datetime(1970,1,1)).total_seconds()
Utiliza esto:
int(dt.strftime("%s"))
Obtengo la respuesta correcta en tu ejemplo usando el segundo método.
EDIT: Un poco de seguimiento... Después de algunos comentarios (ver más abajo), tuve curiosidad por la falta de apoyo o documentación para %s
en strftime
. Esto es lo que he encontrado:
En el código fuente de Python para datetime
y time
, la cadena STRFTIME_FORMAT_CODES
nos dice:
"Other codes may be available on your platform.
See documentation for the C library strftime function."
Así que ahora si man strftime
(en sistemas BSD como Mac OS X), encontrará soporte para %s
:
"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."
De todos modos, por eso %s
funciona en los sistemas que lo hace. Pero hay mejores soluciones para el problema de OP's (que tienen en cuenta las zonas horarias). Vea la respuesta aceptada de @abarnert'aquí.
Bueno, al convertir a un sello de tiempo unix, python está básicamente asumiendo UTC, pero al convertir de vuelta te dará una fecha convertida a tu zona horaria local.
Ver esta pregunta/respuesta; https://stackoverflow.com/questions/18812638/get-timezone-used-by-datetime-datetime-fromtimestamp