Подтвердить что ты не робот

Невозможно сравнить наивные и осведомленные данные 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() для распознавания даты и времени локали?

4b9b3361

Ответ 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, это значительно упрощает дело с такими вещами.