En Python, ¿cómo se convierte un objeto `datetime` en segundos?

226

Disculpas por la simple pregunta ... Soy nuevo en Python ... He buscado y parece que nada funciona.

Tengo un montón de objetos de fecha y hora y quiero calcular el número de segundos desde una hora fija en el pasado para cada uno (por ejemplo, desde el 1 de enero de 1970).

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

Esto parece solo diferenciar entre fechas que tienen días diferentes:

t.toordinal()

Cualquier ayuda es muy apreciada.

Nathan Lippi
fuente
2
Probablemente los convertiría a S desde la época e iría desde allí: int(t.timestamp())
nerdwaller el
para la operación opuesta, vaya aquí: convert-seconds-since-epoch-to-a-datetime-object
Trevor Boyd Smith

Respuestas:

233

Para la fecha especial del 1 de enero de 1970 hay varias opciones.

Para cualquier otra fecha de inicio, debe obtener la diferencia entre las dos fechas en segundos. Restar dos fechas da un timedeltaobjeto, que a partir de Python 2.7 tiene una total_seconds()función.

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

La fecha de inicio generalmente se especifica en UTC, por lo que para obtener los resultados correctos, también datetimedebe incluirla en UTC. Si aún datetimeno está en UTC, deberá convertirlo antes de usarlo o adjuntar una tzinfoclase que tenga el desplazamiento adecuado.

Como se señaló en los comentarios, si tiene un tzinfoadjunto a su datetime, también necesitará uno en la fecha de inicio o la resta fallará; para el ejemplo anterior, agregaría tzinfo=pytz.utcsi usa Python 2 o tzinfo=timezone.utcsi usa Python 3.

Mark Ransom
fuente
1
Python ahora me advierte: "TypeError: no se pueden restar los tiempos de fecha ingenuos y conscientes del desplazamiento" ¿Cuál es la mejor solución para solucionarlo?
Aaron Ash
2
@Charybdis, inténtalo datetime.datetime(1970,1,1,tzinfo=pytz.utc).
Mark Ransom
99
Considere usar: datetime.datetime.utcfromtimestamp(0) He usado esto para obtener la 'época' fácilmente. Tenga en cuenta que la época no siempre es la misma en todos los sistemas.
DA
3
Tenga mucho cuidado con las zonas horarias aquí. Estoy en UTC + 2, lo que significa que la salida time.time()y datetime.now() - datetime(1970, 1, 1)difieren en 7200 segundos. Más bien uso (t - datetime.datetime.fromtimestamp(0)).total_seconds(). No lo use utcfromtimestamp(0)si desea convertir una fecha y hora en su zona horaria local.
Carl
2
@DA: Python no admite épocas que no sean POSIX . Todos los sistemas donde funciona Python usan la misma época: 1970-01-01 00:00:00 UTC
jfs
130

Para obtener el tiempo de Unix (segundos desde el 1 de enero de 1970):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0
Mark Byers
fuente
22
tenga cuidado al usar time.mktime porque es expreso de la hora local y depende de la plataforma
Shih-Wen Su
77
Ten cuidado de verdad. Me mordió el culo a lo grande
Arg
se supone que tes una hora local. La compensación de UTC para la zona horaria local puede haber sido diferente en el pasado y si mktime()(biblioteca C) no tiene acceso a los datos históricos de la zona horaria en una plataforma determinada, entonces puede fallar ( pytzes una forma portátil de acceder a la base de datos tz). Además, la hora local puede ser ambigua, por ejemplo, durante las transiciones DST: necesita información adicional para desambiguar , por ejemplo, si sabe que los valores de fecha / hora consecutivos deberían aumentar en un archivo de registro
jfs
1
Tenga cuidado al usar esto con tiempos que tienen fracciones de segundo. time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())da como resultado 1564819506.0, bajando silenciosamente los milisegundos, pero datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(respuesta de Andrzej Pronobis) da como resultado 1564819506.912el resultado esperado.
Alex
128

A partir de Python 3.3, esto se vuelve súper fácil con el datetime.timestamp()método. Por supuesto, esto solo será útil si necesita la cantidad de segundos desde 1970-01-01 UTC.

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

El valor de retorno será un flotante que representa fracciones pares de un segundo. Si la fecha y hora es ingenua en la zona horaria (como en el ejemplo anterior), se supondrá que el objeto de fecha y hora representa la hora local, es decir, será el número de segundos desde la hora actual en su ubicación hasta 1970-01-01 UTC.

Andrzej Pronobis
fuente
3
Quien haya rechazado esto, ¿podría explicar por qué?
Andrzej Pronobis
55
Supongo que el voto negativo se debe a la etiqueta python-2.7 en la pregunta (es solo una suposición).
jfs
3
Esta debería ser la respuesta aceptada / la respuesta aceptada debería actualizarse en consecuencia.
DreamFlasher
11
Es hora de actualizar, supongo;)
DreamFlasher
¿Es posible calcular esta distancia desde otra fecha de inicio? (
Me
29

Tal vez fuera del tema: para obtener el tiempo UNIX / POSIX de datetime y convertirlo de nuevo:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

Tenga en cuenta que diferentes zonas horarias tienen un impacto en los resultados, por ejemplo, mis retornos actuales de TZ / DST:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

por lo tanto, uno debería considerar la normalización a UTC mediante el uso de versiones UTC de las funciones.

Tenga en cuenta que el resultado anterior se puede utilizar para calcular el desplazamiento UTC de su zona horaria actual. En este ejemplo, esto es + 1h, es decir, UTC + 0100.

Referencias

Robert Lujo
fuente
mktime()puede fallar . En general, necesita pytzconvertir la hora local a utc, para obtener la marca de tiempo POSIX.
jfs
calendar.timegm () parece ser la versión utc de time.mktime ()
frankster
27

int (t.strftime("%s")) también funciona

dan3
fuente
1
Funciona para mí en Python 2.7, con import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(según lo especificado por OP). Pero realmente, dudo que% s sea un formato de tiempo agregado recientemente.
dan3
1
@ dan3: mal. %sno es compatible (puede funcionar en algunas plataformas si tes un objeto de fecha y hora ingenuo que representa la hora local y si la biblioteca C local tiene acceso a la base de datos tz, de lo contrario, el resultado puede ser incorrecto). No lo uses
jfs
%sno está documentado en ningún lado. Lo siembro en código real y me preguntaba qué es esto y miro en la documentación y no existe tal cosa %s. Solo hay una gran S solo por unos segundos.
VStoykov
13

de los documentos de Python:

timedelta.total_seconds()

Devuelve el número total de segundos contenidos en la duración. Equivalente a

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

calculado con verdadera división habilitada.

Tenga en cuenta que para intervalos de tiempo muy largos (más de 270 años en la mayoría de las plataformas) este método perderá precisión de microsegundos.

Esta funcionalidad es nueva en la versión 2.7.

Miguel
fuente
1
hay un pequeño problema con el cálculo, debe ser 10 6 en lugar de 10 * 6 ... td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 6) / 10 ** 6
sdu
@sdu great catch: el doble asterisco está en mi respuesta, pero stackoverflow lo consume, los intentos de rectificar solo envalentonan el texto.
Michael
2

Para convertir un objeto de fecha y hora que represente la hora en UTC a la marca de tiempo POSIX :

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

Para convertir un objeto de fecha y hora que representa la hora en la zona horaria local a la marca de tiempo POSIX:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

Consulte ¿Cómo convierto la hora local a UTC en Python? Si la base de datos tz está disponible en una plataforma determinada; una solución solo stdlib puede funcionar .

Siga los enlaces si necesita soluciones para las <3.3versiones de Python.

jfs
fuente
1

Probé el calendar.timegm de la biblioteca estándar y funciona bastante bien:

# convert a datetime to milliseconds since Epoch
def datetime_to_utc_milliseconds(aDateTime):
    return int(calendar.timegm(aDateTime.timetuple())*1000)

Ref: https://docs.python.org/2/library/calendar.html#calendar.timegm

Shaohong Li
fuente
despoja fracciones de segundo. Se supone que aDateTimees una hora UTC
jfs