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.



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.


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

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.


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


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


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.


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.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.