Convierta fecha y hora a marca de tiempo Unix y vuelva a convertirla en Python
Tengo dt = datetime(2013,9,1,11)
y me gustaría obtener una marca de tiempo Unix de este objeto de fecha y hora.
Cuando lo hago, (dt - datetime(1970,1,1)).total_seconds()
obtengo la marca de tiempo 1378033200
.
Al volver a convertirlo usando datetime.fromtimestamp
obtuve datetime.datetime(2013, 9, 1, 6, 0)
.
La hora no coincide. ¿Qué me perdí aquí?
la solución es
import time
import datetime
d = datetime.date(2015,1,5)
unixtime = time.mktime(d.timetuple())
Si desea convertir una fecha y hora de Python a segundos desde la época, debe hacerlo explícitamente:
>>> import datetime
>>> datetime.datetime(2012, 04, 01, 0, 0).strftime('%s')
'1333234800'
>>> (datetime.datetime(2012, 04, 01, 0, 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1333238400.0
En Python 3.3+ puedes usar timestamp()
en su lugar:
>>> import datetime
>>> datetime.datetime(2012, 4, 1, 0, 0).timestamp()
1333234800.0
Lo que te perdiste aquí son las zonas horarias.
Presumiblemente tienes cinco horas fuera de UTC, por lo que 2013-09-01T11:00:00 local y 2013-09-01T06:00:00Z son la misma hora.
Debe leer la parte superior de los datetime
documentos, que explican las zonas horarias y los objetos "ingenuos" y "conscientes".
Si su fecha y hora ingenua original era UTC, la forma de recuperarla es usarla utcfromtimestamp
en lugar de fromtimestamp
.
Por otro lado, si su fecha y hora ingenua original era local, no debería haberle restado una marca de tiempo UTC en primer lugar; utilizar datetime.fromtimestamp(0)
en su lugar.
O, si tenía un objeto de fecha y hora consciente, necesita usar una época local (consciente) en ambos lados o convertir explícitamente hacia y desde UTC.
Si tiene Python 3.3 o posterior, o puede actualizarlo, puede evitar todos estos problemas simplemente usando el timestamp
método en lugar de intentar descubrir cómo hacerlo usted mismo. E incluso si no lo hace, puede considerar tomar prestado su código fuente .
(Y si puede esperar a Python 3.4, parece que PEP 341 probablemente llegue a la versión final, lo que significa que todo lo que JF Sebastian y yo estábamos hablando en los comentarios debería poder realizarse solo con stdlib, y funciona de la misma manera tanto en Unix como en Windows).
En lugar de esta expresión para crear una marca de tiempo POSIX dt
,
(dt - datetime(1970,1,1)).total_seconds()
Utilizar esta:
int(dt.strftime("%s"))
Obtengo la respuesta correcta en su ejemplo usando el segundo método.
EDITAR: Algo de seguimiento... Después de algunos comentarios (ver más abajo), tenía curiosidad por la falta de soporte o documentación para %s
in strftime
. Esto es lo que encontré:
En la 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."
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, es por eso que %s
funciona en los sistemas que lo hace. Pero existen mejores soluciones al problema de OP (que tienen en cuenta las zonas horarias). Vea la respuesta aceptada de @abarnert aquí.