Convertir datetime a marca de tiempo Unix y convertirlo de nuevo en python


Tengo dt = datetime(2013,9,1,11), y me gustaría obtener una marca de tiempo Unix de este objeto datetime.

Cuando lo hago dt - datetime(1970,1,1)).total_seconds() tengo la marca de tiempo 1378033200.

Al convertirlo de nuevo usando datetime.fromtimestamp tengo datetime.datetime(2013, 9, 1, 6, 0).

La hora no coincide. ¿Qué me perdí aquí?

Author: Kun, 2013-11-06

9 answers

Lo que te perdiste aquí son 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.

Usted necesita leer la parte superior de la datetime documentos, que explican sobre zonas horarias y objetos" ingenuos "y" conscientes".

Si su fecha y hora ingenua original era UTC, la forma de recuperarla es usar utcfromtimestamp en lugar de fromtimestamp.

Por otro lado, si su fecha y hora ingenua original era local, usted no debería haber restado una marca de tiempo UTC en primer lugar; use datetime.fromtimestamp(0) en su lugar.

O, si tenía un objeto datetime consciente, necesita usar una época local (consciente) en ambos lados, o convertir explícitamente hacia y desde UTC.

Si usted tiene, o puede actualizar a, Python 3.3 o posterior, puede evitar todos estos problemas simplemente utilizando el timestamp método en lugar de tratar de averiguar cómo hacerlo usted mismo. E incluso si no lo hace, es posible que desee considerar tomando 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 estábamos hablando en los comentarios deberían ser factibles solo con stdlib, y funcionar de la misma manera tanto en Unix como en Windows.)

 74
Author: abarnert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-22 19:23:28

La Solución es

import time
import datetime
d = datetime.date(2015,1,5)

unixtime = time.mktime(d.timetuple())
 100
Author: DmitrySemenov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-13 03:21:47

En lugar de esta expresión para crear una marca de tiempo POSIX desde dt,

(dt - datetime(1970,1,1)).total_seconds()

Usa esto:

int(dt.strftime("%s"))

Obtengo la respuesta correcta en tu ejemplo usando el segundo método.

EDITAR: Algún seguimiento... Después de algunos comentarios (ver más abajo), tenía curiosidad por la falta de apoyo o documentación para %s en 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."

Así que ahora si man strftime (en BSD sistemas 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 hay mejores soluciones al problema de OP (que tienen en cuenta las zonas horarias). Vea la respuesta aceptada de @abarnert aquí.

 46
Author: Darren Stone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-14 06:31:09

Si desea convertir una datetime de python a segundos desde epoch, 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 + puede utilizar timestamp() en su lugar:

>>> import datetime
>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0
 27
Author: Francisco Tomé Costa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-09 14:18:06

Si su objeto datetime representa la hora UTC, no use la hora.mktime, ya que asume que la tupla está en tu zona horaria local. En su lugar, utilice calendario.timegm:

>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60
 3
Author: Matt Kramer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-28 07:10:50

Bueno, cuando se convierte A la marca de tiempo unix, python básicamente asume UTC, pero mientras se convierte de nuevo le dará una fecha convertida a su zona horaria local.

Ver esta pregunta/respuesta; Obtener la zona horaria utilizada por datetime.datetime.fromestamp()

 2
Author: Ronald Portier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:45

Te has perdido la información de la zona horaria (ya respondida, de acuerdo)

arrow package permite evitar esta tortura con datetimes; Ya está escrito, probado, pypi-published, cross-python (2.6 - 3.xx).

Todo lo que necesitas: pip install arrow (o añadir a dependencias)

Solución para su caso

dt = datetime(2013,9,1,11)
arrow.get(dt).timestamp
# >>> 1378033200

bc = arrow.get(1378033200).datetime
print(bc)
# >>> datetime.datetime(2013, 9, 1, 11, 0, tzinfo=tzutc())
print(bc.isoformat())
# >>> '2013-09-01T11:00:00+00:00'
 2
Author: maxkoryukov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-01 13:02:35
def dt2ts(dt):
    import calendar
    import time
    from dateutil import tz

    if dt.tzinfo is None:
        return int(time.mktime(dt.timetuple()))
    utc_dt = dt.astimezone(tz.tzutc()).timetuple()
    return calendar.timegm(utc_dt)

Si desea la marca de tiempo UTC :time.mktime solo para local dt .Use calendar.timegm es seguro, pero dt debe la zona utc para cambiar la zona a utc

 1
Author: wyx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-29 04:00:44

Para trabajar con zonas horarias UTC:

time_stamp = calendar.timegm(dt.timetuple())

datetime.utcfromtimestamp(time_stamp)
 0
Author: Dede,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-25 16:51:07