Encuentre si han pasado 24 horas entre fechas y horas
Tengo el siguiente método:
# last_updated is a datetime() object, representing the last time this program ran
def time_diff(last_updated):
day_period = last_updated.replace(day=last_updated.day + 1,
hour=1,
minute=0,
second=0,
microsecond=0)
delta_time = day_period - last_updated
hours = delta_time.seconds // 3600
# make sure a period of 24hrs have passed before shuffling
if hours >= 24:
print "hello"
else:
print "do nothing"
Quiero saber si han pasado 24 horas desde entonces last_updated
, ¿cómo puedo hacerlo en Python?
Si last_updated
es un objeto ingenuo de fecha y hora que representa la hora en UTC:
from datetime import datetime, timedelta
if (datetime.utcnow() - last_updated) > timedelta(hours=24):
# more than 24 hours passed
Si last_updated
es la hora local (objeto de fecha y hora ingenuo (sin reconocimiento de zona horaria):
import time
DAY = 86400
now = time.time()
then = time.mktime(last_updated.timetuple())
if (now - then) > DAY:
# more than 24 hours passed
Si last_updated
es una hora ambigua, por ejemplo, la hora durante una transición de fin de horario de verano (una vez al año en muchas zonas horarias), entonces hay una probabilidad del cincuenta por ciento de que mktime()
arroje un resultado incorrecto (por ejemplo, con una diferencia de una hora).
time.mktime()
También puede fallar si time
la biblioteca C no utiliza una base de datos de zona horaria histórica en una plataforma determinada y el desplazamiento UTC para la zona horaria local era diferente en last_updated
ese momento comparado con el actual. Puede aplicarse a más de un tercio de todas las zonas horarias durante el último año. Linux, OS X, las versiones recientes de Windows tienen la base de datos tz (no sé si las versiones antiguas de Windows funcionarían para fechas tan pasadas).
Cuidado: puede resultar tentador escribir datetime.now() - last_updated
(similar al caso de UTC), pero se garantiza que fallará en todas las plataformas si el desplazamiento de UTC fue diferente en el last_updated
momento (es posible en muchas zonas horarias). mktime()
La solución basada en tz puede utilizar la base de datos tz al menos en algunas plataformas y, por lo tanto, puede manejar los cambios en el desplazamiento UTC por cualquier motivo allí.
Para portabilidad, puede instalar la base de datos tz. Lo proporciona un pytz
módulo en Python. tzlocal
puede devolver pytz
la zona horaria correspondiente a la zona horaria local:
from datetime import datetime, timedelta
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone() # local timezone
then = tz.normalize(tz.localize(last_updated)) # make it timezone-aware
now = datetime.now(tz) # timezone-aware current time in the local timezone
if (now - then) > timedelta(hours=24):
# more than 24 hours passed
Funciona incluso si la compensación UTC fue diferente en el pasado. Pero no puede (ni tampoco time.mktime()
) corregir tiempos ambiguos ( tz.localize()
elige is_dst=False
el tiempo de forma predeterminada). tz.normalize()
se llama para ajustar tiempos no existentes, por ejemplo, aquellos que corresponden a una transición de inicio de horario de verano (no debería afectar el resultado).
El código anterior supone que last_updated
es un objeto de fecha y hora ingenuo (sin información de zona horaria asociada). Si last_updated
es un objeto de fecha y hora consciente, entonces es fácil convertirlo a UTC:
from datetime import datetime, timedelta
then_in_utc = last_updated.replace(tzinfo=None) - last_updated.utcoffset()
if (datetime.utcnow() - then_in_utc) > timedelta(hours=24):
# more than 24 hours passed
Nota general: ahora debería comprender por qué la gente recomienda trabajar con la hora UTC y utilizar la hora local sólo para la visualización.
Solo para aclarar algunas cosas, porque no creo que todos hagamos uso de la time
biblioteca de Python. Cuando usas datetime
, que es especialmente en Django una práctica muy común, si haces la comparación de esta manera:
if (now - then) > DAY:
fracasará enormemente . Esto se debe a que no se puede comparar datetime.timedelta
con int
.
La solución a esto es convertir tus objetos a segundos.
Por ejemplo:
from datetime import datetime
then = datetime_object
now = datetime.now()
if (now - then).total_seconds() > NUMBER_OF_SECONDS:
# do something
Espero haber ayudado a quienes hayan tenido problemas al respecto.
Salud