J'essaie de comparer la date et l'heure actuelles avec les dates et heures spécifiées dans les modèles à l'aide d'opérateurs de comparaison:
if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:
Le script fait une erreur avec:
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'ai aussi Django en utilisant la date et l'heure locales.
Ce que je n'ai pas réussi à trouver, c'est le format utilisé par Django pour DateTimeField (). Est-ce naïf ou conscient? Et comment puis-je obtenir que datetime.now () reconnaisse les paramètres régionaux datetime?
Par défaut, l'objet datetime
est naive
en Python. Vous devez donc définir les deux objets naïfs ou conscients 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)
# now both the datetime objects are aware, and you can compare them
Remarque: Cela déclencherait 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)
En passant, vous pouvez formater un horodatage UNIX dans l'objet datetime.datetime avec les 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)
datetime.datetime.now
n'est pas sensible au fuseau horaire.
Django vient avec une aide pour cela, ce qui nécessite pytz
from Django.utils import timezone
now = timezone.now()
Vous devriez pouvoir comparer now
à challenge.datetime_start
ne ligne de solution de code
if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo):
pass #some code
Version expliquée:
# 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
Sommaire:
Vous devez ajouter les informations de fuseau horaire à votre now()
datetime.
Cependant, vous devez ajouter le fuseau horaire identique de la variable de référence; c'est pourquoi j'ai d'abord lu l'attribut tzinfo
.
Désactiver le fuseau horaire. Utiliser challenge.datetime_start.replace(tzinfo=None);
Vous pouvez également utiliser replace(tzinfo=None)
pour d'autres date/heure.
if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None):
Donc, la façon dont je réglerais ce problème est de m'assurer que les deux dates sont dans le bon fuseau horaire.
Je peux voir que vous utilisez datetime.now()
qui renverra l'heure actuelle du système, sans définir tzinfo.
tzinfo est l’information attachée à une date/heure pour lui permettre de savoir dans quel fuseau horaire il se trouve. Si vous utilisez une date/heure naïve, vous devez être cohérent sur l'ensemble de votre système. Je recommande fortement d'utiliser uniquement datetime.utcnow()
étant donné que tzinfo est associé à certains moments de la création de l'heure-heure, veillez à ce que ceux-ci soient localisés (avec tzinfo associé) dans le fuseau horaire correspondant.
Jetez un oeil à Delorean , cela facilite beaucoup le travail avec ce genre de chose.
Cela fonctionne de moi. Ici, je vais chercher la table créée datetime et ajouter 10 minutes à la date/heure. plus tard, en fonction de l'heure actuelle, les opérations d'expiration sont effectuées.
from datetime import datetime, time, timedelta
import pytz
Ajout de 10 minutes sur la base de données datetime
table_datetime = '2019-06-13 07: 49: 02.832969' (exemple)
# Added 10 minutes on database datetime
# table_datetime = '2019-06-13 07:49:02.832969' (example)
table_expire_datetime = table_datetime + timedelta(minutes=10 )
# Current datetime
current_datetime = datetime.now()
# replace the timezone in both time
expired_on = table_expire_datetime.replace(tzinfo=utc)
checked_on = current_datetime.replace(tzinfo=utc)
if expired_on < checked_on:
print("Time Crossed)
else:
print("Time not crossed ")
Cela a fonctionné pour moi.