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.
To fix TypeError: can't compare offset-naive and offset-aware datetimes with Python, we can use the utc. localize method to convert both times to aware datetimes. to call utc. localize to convert datetime_start and datetime_end to time zone aware datetimes.
naive vs aware So a datetime object can be either offset naive or offset aware. A timezone's offset refers to how many hours the timezone is from Coordinated Universal Time (UTC). A naive datetime object contains no timezone information. The easiest way to tell if a datetime object is naive is by checking tzinfo.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With