Невозможно сравнить наивные и осведомленные данные datetime.now() <= challenge.datetime_end
Я пытаюсь сравнить текущую дату и время с датами и временем, указанными в моделях с помощью операторов сравнения:
if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:
Ошибки script:
TypeError: can't compare offset-naive and offset-aware datetimes
Модели выглядят так:
class Fundraising_Challenge(models.Model):
name = models.CharField(max_length=100)
datetime_start = models.DateTimeField()
datetime_end = models.DateTimeField()
У меня также есть django, используя дату и время локали.
То, что я не смог найти, - это формат, используемый django для DateTimeField(). Это наивно или известно? И как мне получить datetime.now() для распознавания даты и времени локали?
Ответы
Ответ 1
По умолчанию объект datetime
naive
в Python, поэтому вам нужно сделать оба объекта наивными или осведомленными объектами datetime
. Это можно сделать с помощью:
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
Примечание: это вызовет ValueError
если tzinfo
уже установлена. Если вы не уверены в этом, просто используйте
start_time = challenge.datetime_start.replace(tzinfo=utc)
end_time = challenge.datetime_end.replace(tzinfo=utc)
Кстати, вы можете отформатировать метку времени UNIX в объекте datetime.datetime с информацией о часовом поясе следующим образом
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)
Ответ 2
datetime.datetime.now
не осведомлен о часовом поясе.
Django поставляется с помощником для этого, для которого требуется pytz
from django.utils import timezone
now = timezone.now()
Вы должны иметь возможность сравнить now
с challenge.datetime_start
Ответ 3
Одна строка кода решения
if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo):
pass #some code
Разъясненная версия:
# 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
Резюме:
Вы должны добавить информацию о часовом поясе к вашему now()
datetime.
Однако вы должны добавить тот же часовой пояс для ссылочной переменной; Вот почему я впервые прочитал атрибут tzinfo
.
Ответ 4
Отключить часовой пояс. Используйте challenge.datetime_start.replace(tzinfo=None);
Вы также можете использовать replace(tzinfo=None)
для другой даты и времени.
if challenge.datetime_start.replace(tzinfo=None) <= datetime.now().replace(tzinfo=None) <= challenge.datetime_end.replace(tzinfo=None):
Ответ 5
Таким образом, я разрешаю эту проблему, чтобы убедиться, что два времени находятся в правильном часовом поясе.
Я вижу, что вы используете datetime.now()
, который вернет текущее время систем, без набора tzinfo.
tzinfo - это информация, привязанная к дате времени, чтобы сообщить ему, в какой временной зоне она находится. Если вы используете наивное datetime, вам нужно быть последовательным в вашей системе. Я бы очень рекомендовал использовать только datetime.utcnow()
видя, что где-то вы создаете дату и время, связанное с ними tzinfo, вам нужно убедиться, что они локализованы (связаны с tzinfo) с правильным часовым поясом.
Взгляните на Delorean, это значительно упрощает дело с такими вещами.