django 1.4 - невозможно сравнить дату и время без смещения и с учетом смещения

85

Я занимаюсь переносом приложения с django 1.2 на 1.4.

У меня есть объект ежедневной задачи, который содержит время дня, когда задача должна быть завершена:

class DailyTask(models.Model):
    time = models.TimeField()
    last_completed = models.DateTimeField()
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=1000)
    weekends = models.BooleanField()

    def __unicode__(self):
        return '%s' % (self.name)

    class Meta:
        db_table = u'dailytask'
        ordering = ['name']

Чтобы проверить, нужно ли выполнить задачу сегодня, у меня есть следующий код:

def getDueDailyTasks():
    dueDailyTasks=[]
    now = datetime.datetime.now()
    try:
        dailyTasks = DailyTask.objects.all()
    except dailyTask.DoesNotExist:
        return None
    for dailyTask in dailyTasks:
        timeDue = datetime.datetime(now.year,now.month,now.day,dailyTask.time.hour,dailyTask.time.minute,dailyTask.time.second)
        if timeDue<now and timeDue>dailyTask.last_completed:
            if dailyTask.weekends==False and now.weekday()>4:
                pass
            else:
                dueDailyTasks.append({'id':dailyTask.id,
                            'due':timeDue,
                             'name': dailyTask.name,
                             'description':dailyTask.description})
    return dueDailyTasks

Это нормально работало под 1.2, но под 1.4 я получаю сообщение об ошибке:

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

из-за линии

if timeDue<now and timeDue>dailyTask.last_completed

и оба предложения сравнения вызывают эту ошибку.

Я попытался сделать timeDue осведомленным о часовом поясе, добавив pytz.UTC в качестве аргумента, но это все равно вызывает ту же ошибку.

Я читал некоторые документы о часовых поясах, но не понимаю, нужно ли мне просто указать часовой пояс timeDue или мне нужно внести фундаментальные изменения в мою базу данных и существующие данные.

мипмип
источник

Ответы:

168

Проверьте подробный документ для получения подробной информации.

Обычно используется django.utils.timezone.nowдля создания текущего значения даты и времени с учетом смещения

>>> from django.utils import timezone
>>> timezone.now()
datetime.datetime(2012, 5, 18, 13, 0, 49, 803031, tzinfo=<UTC>)

И django.utils.timezone.make_awareчтобы сделать дату и время с учетом смещения

>>> timezone.make_aware(datetime.datetime.now(), timezone.get_default_timezone())
datetime.datetime(2012, 5, 18, 21, 5, 53, 266396, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)

Затем вы можете сравнить обе даты с учетом смещения без проблем.

Кроме того, вы можете преобразовать дату и время со смещением в наивное смещение даты и времени datetime.datetime.now(), удалив информацию о часовом поясе, а затем ее можно будет сравнить с нормальным , под utc.

>>> t = timezone.now() # offset-awared datetime
>>> t.astimezone(timezone.utc).replace(tzinfo=None)
datetime.datetime(2012, 5, 18, 13, 11, 30, 705324)

USE_TZэто True«по умолчанию» ( на самом деле это Falseпо умолчанию, но settings.pyфайл , сгенерированный django-admin.py startprojectнабором его True), а затем , если вашей БД поддерживает часовые пояса, известны время, значение времени , связанное с модельными полями будет временной зоной, в курсе. вы можете отключить его, установив USE_TZ=False(или просто убрав USE_TZ=True) в настройках.

окм
источник
4
Django не хранит известное время для TimeField, а только для DateTimeField. Это действительно раздражает, поскольку объект python datetime.time поддерживает TZINFO точно так же, как объекты datetime.datetime. Интересно, они исправят это в следующем выпуске. Кстати, я тестировал его на сервере базы данных postres 9.1.
tejinderss
@tejinderss: datetime.timeневерно. Нет смысла сохранять 'Asia/Shanghai'часовой пояс, если вы не знаете дату (смещение utc может отличаться для одного и того же времени, но в разные даты).
jfs
@okm: make_aware(datetime.now(), get_default_timezone())не работает, если get_default_timezone()отличается от вашего местного часового пояса (так и должно быть, но не полностью). Просто используйте timezone.now()вместо этого (это зависит от часового пояса, если USE_TZесть True).
jfs