267 votes

Ne peut pas comparer datetime.now() naive et aware <= challenge.datetime_end

Je tente de comparer la date et l'heure actuelles avec les dates et heures spécifiées dans les modèles en utilisant des opérateurs de comparaison :

if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:

Le script retourne une erreur :

TypeError: can't compare offset-naive and offset-aware datetimes

Les modèles ressemblent à ceci :

class Fundraising_Challenge(models.Model):
    name = models.CharField(max_length=100)
    datetime_start = models.DateTimeField()
    datetime_end = models.DateTimeField()

J'utilise également django avec des dates et heures locales.

Ce que je n'ai pas réussi à trouver, c'est le format que django utilise pour DateTimeField(). Est-il naïf ou conscient? Et comment puis-je faire en sorte que datetime.now() reconnaisse la date et l'heure locales?

238voto

bkvirendra Points 1503

Par défaut, l'objet datetime est naïf en Python, vous devez donc les rendre tous les deux naïfs ou aware objets datetime. Cela peut être fait en utilisant :

import datetime
import pytz

utc=pytz.UTC

challenge.datetime_start = utc.localize(challenge.datetime_start) 
challenge.datetime_end = utc.localize(challenge.datetime_end) 
# maintenant les deux objets datetime sont de type aware, et vous pouvez les comparer

Remarque : Cela soulèverait une ValueError si tzinfo est déjà défini. Si vous n'êtes pas sûr de cela, utilisez simplement

start_time = challenge.datetime_start.replace(tzinfo=utc)
end_time = challenge.datetime_end.replace(tzinfo=utc)

BTW, vous pourriez formater un horodatage UNIX dans un objet datetime.datetime avec des informations de fuseau horaire comme suit

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)

145voto

Alfredo Aguirre Points 1666

datetime.datetime.now n'est pas conscient du fuseau horaire.

Django vient avec une aide pour cela, qui nécessite pytz

from django.utils import timezone
now = timezone.now()

Vous devriez pouvoir comparer now à challenge.datetime_start

100voto

ePi272314 Points 4098

Une solution d'une seule ligne de code

if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo):
    pass #some code

Version expliquée

# Informations sur le fuseau horaire de votre variable aware du fuseau horaire
timezone = your_timezone_aware_variable.tzinfo

# Date actuelle pour le fuseau horaire de votre variable
now_in_timezone = datetime.datetime.now(timezone)

# Maintenant, vous pouvez faire une comparaison équitable, les deux variables datetime ont le même fuseau horaire
if your_timezone_aware_variable <= now_in_timezone:
    pass #some code

Résumé

Vous devez ajouter les informations de fuseau horaire à votre datetime now().
Cependant, vous devez ajouter le même fuseau horaire que la variable de référence; c'est pourquoi j'ai d'abord lu l'attribut tzinfo.

43voto

Amin Fathi Points 441

Désactiver le fuseau horaire. Utilisez challenge.datetime_start.replace(tzinfo=None);

Vous pouvez également utiliser replace(tzinfo=None) pour d'autres datetime.

if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None):

5voto

ovo Points 530

Pas de module tiers, seulement le module datetime natif.

de 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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X