No se puede comparar datetime.now() ingenuo y consciente (= desafío.datetime_end)
Estoy intentando comparar la fecha y hora actuales con las fechas y horas especificadas en los modelos utilizando operadores de comparación:
if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:
El script falla con:
TypeError: can't compare offset-naive and offset-aware datetimes
Los modelos se ven así:
class Fundraising_Challenge(models.Model):
name = models.CharField(max_length=100)
datetime_start = models.DateTimeField()
datetime_end = models.DateTimeField()
También tengo Django usando fechas y horas locales.
Lo que no he podido encontrar es el formato que usa Django para DateTimeField(). ¿Es ingenuo o consciente? ¿Y cómo consigo que datetime.now() reconozca la fecha y hora local?
De forma predeterminada, el datetime
objeto está naive
en Python, por lo que debes convertirlos en datetime
objetos ingenuos o conscientes. Esto se puede hacer usando:
import datetime
import pytz
utc=pytz.UTC
challenge.datetime_start = utc.localize(challenge.datetime_start)
challenge.datetime_end = utc.localize(challenge.datetime_end)
# now both the datetime objects are aware, and you can compare them
Nota: Esto generaría un error ValueError
si tzinfo
ya está configurado. Si no estás seguro de eso, simplemente usa
start_time = challenge.datetime_start.replace(tzinfo=utc)
end_time = challenge.datetime_end.replace(tzinfo=utc)
Por cierto, puede formatear una marca de tiempo UNIX en el objeto datetime.datetime con información de zona horaria de la siguiente manera
d = datetime.datetime.utcfromtimestamp(int(unix_timestamp))
d_with_tz = datetime.datetime(
year=d.year,
month=d.month,
day=d.day,
hour=d.hour,
minute=d.minute,
second=d.second,
tzinfo=pytz.UTC)
datetime.datetime.now
no tiene en cuenta la zona horaria.
Django viene con un ayudante para esto, que requierepytz
from django.utils import timezone
now = timezone.now()
Deberías poder comparar now
conchallenge.datetime_start
Solución de una línea de código
if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo):
pass #some code
Versión explicada
# Timezone info of your timezone aware variable
timezone = your_timezone_aware_variable.tzinfo
# Current datetime for the timezone of your variable
now_in_timezone = datetime.datetime.now(timezone)
# Now you can do a fair comparison, both datetime variables have the same time zone
if your_timezone_aware_variable <= now_in_timezone:
pass #some code
Resumen
Debe agregar la información de la zona horaria a su now()
fecha y hora.
Sin embargo, debes agregar la misma zona horaria de la variable de referencia; por eso leí por primera vez el tzinfo
atributo.
Desactivar zona horaria. Usarchallenge.datetime_start.replace(tzinfo=None);
También puede utilizarlo replace(tzinfo=None)
para otras fechas y horas .
if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None):
ningún tercero, solo el módulo de fecha y hora nativo.
from datetime import datetime, timedelta, timezone
time1 = datetime.strptime('2021-07-15T00:22:02+0000', '%Y-%m-%dT%H:%M:%S%z')
time2 = datetime(2021, 7, 15, tzinfo=timezone(offset=timedelta()))
if time1 < time2:
print(True)