python - No se puede comparar ingenuo y consciente datetime.now()<= challenge.datetime_end
django comparison (5)
Estoy tratando de comparar la fecha y la hora actual con las fechas y horas especificadas en los modelos que usan operadores de comparación:
if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:
El script se equivoca 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 la fecha y la hora de la localidad.
Lo que no he podido encontrar es el formato que django usa para DateTimeField (). ¿Es ingenuo o consciente? ¿Y cómo obtengo datetime.now () para reconocer la fecha y hora local?
De forma predeterminada, el objeto datetime
es naive
en Python, por lo que debe hacer que ambos sean ingenuos o datetime
conscientes de los objetos datetime
. 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 ValueError
si tzinfo
ya está configurado. Si no está seguro de eso, solo use
start_time = challenge.datetime_start.replace(tzinfo=utc)
end_time = challenge.datetime_end.replace(tzinfo=utc)
Por cierto, podría formatear una marca de tiempo de UNIX en el objeto datetime.datetime con la información de la 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)
Desactivar zona horaria. Utilice challenge.datetime_start.replace(tzinfo=None);
También puede usar replace(tzinfo=None)
para otra fecha y hora .
if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None):
Entonces, la forma en que resolvería este problema es asegurarse de que los dos tiempos de fecha estén en la zona horaria correcta.
Veo que está usando datetime.now()
que devolverá la hora actual del sistema, sin el conjunto de tzinfo.
tzinfo es la información adjunta a una fecha y hora para que sepa en qué zona horaria se encuentra. Si usa la fecha de inicio de manera ingenua, necesita ser constante en todo su sistema. Recomiendo encarecidamente solo utilizar datetime.utcnow()
ya que en algún lugar estás creando datetime que tienen asociado a tzinfo, lo que debes hacer es asegurarte de que estén localizados (tiene tzinfo asociado) a la zona horaria correcta.
Echa un vistazo a Delorean , hace que lidiar con este tipo de cosas sea mucho más fácil.
datetime.datetime.now
no es consciente de la zona horaria.
Django viene con un ayudante para esto, que requiere pytz
from django.utils import timezone
now = timezone.now()
Debería poder comparar now
con challenge.datetime_start
Una línea de solución 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 hora now()
.
Sin embargo, debe agregar la misma zona horaria de la variable de referencia; es por eso que primero leí el atributo tzinfo
.