ChatGPT解决这个技术问题 Extra ChatGPT

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

I am in the process of migrating an application from django 1.2 To 1.4.

I have a daily task object which contains a time of day that task should be completed:

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']

In order to check if a task is still required to be completed today, I have the following code:

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

This worked fine under 1.2, But under 1.4 I get the error:

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

due to the line

if timeDue<now and timeDue>dailyTask.last_completed

and both comparison clauses throw this error.

I have tried making timeDue timezone aware by adding pytz.UTC as an argument, but this still raises the same error.

I've read some of the docs on timezones but am confused as to whether I just need to make timeDue timezone aware, or whether I need to make a fundamental change to my db and existing data.


o
okm

Check the thorough document for detail info.

Normally, use django.utils.timezone.now to make an offset-aware current datetime

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

And django.utils.timezone.make_aware to make an offset-aware datetime

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

You could then compare both offset-aware datetimes w/o trouble.

Furthermore, you could convert offset-awared datetime to offset-naive datetime by stripping off timezone info, then it could be compared w/ normal datetime.datetime.now(), under 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 is True 'by default' (actually it's False by default, but the settings.py file generated by django-admin.py startproject set it to True), then if your DB supports timezone-aware times, values of time-related model fields would be timezone-aware. you could disable it by setting USE_TZ=False(or simply remove USE_TZ=True) in settings.


Django does not store aware times for TimeField, it only does for DateTimeField. Its really annoying, as python datetime.time object does support TZINFO just like datetime.datetime objects. I wonder they would fix it in next release. Btw i have tested it on postres 9.1 database server.
@tejinderss: datetime.time is wrong. There is no point to store 'Asia/Shanghai' timezone if you don't know the date (the utc offset may be different for the same time but on different dates).
@okm: make_aware(datetime.now(), get_default_timezone()) fails if get_default_timezone() differs from your local timezone (it should be but it is not entire relyable). Just use timezone.now() instead (it is timezone-aware if USE_TZ is True).