python django datetime comparison

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 .