2012-05-18 33 views
77

Tôi đang trong quá trình di chuyển một ứng dụng từ django 1.2 đến 1.4.django 1.4 - không thể so sánh các khoảng thời gian bù trừ-ngây thơ và bù trừ nhận thức

Tôi có một đối tượng nhiệm vụ hàng ngày, trong đó có một thời gian trong ngày nhiệm vụ cần được hoàn thành:

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

Để kiểm tra xem một công việc vẫn phải được hoàn thành ngày hôm nay, tôi có đoạn mã sau:

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 

này làm việc tốt dưới 1.2, Nhưng dưới 1,4 tôi nhận được lỗi:

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

do dòng

if timeDue<now and timeDue>dailyTask.last_completed 

và cả hai mệnh đề so sánh đều ném lỗi này.

Tôi đã thử làm cho múi giờ của bạn được nhận biết bằng cách thêm pytz.UTC làm đối số, nhưng điều này vẫn làm tăng cùng một lỗi.

Tôi đã đọc một số tài liệu về múi giờ nhưng bị nhầm lẫn về việc liệu tôi có cần nhận biết múi giờ timeDue hay không hoặc liệu tôi có cần thực hiện thay đổi cơ bản cho db và dữ liệu hiện có của mình hay không.

Trả lời

153

Kiểm tra the thorough document để biết thông tin chi tiết.

Thông thường, sử dụng django.utils.timezone.now để làm cho một dòng datetime bù đắp-aware

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

django.utils.timezone.make_aware để thực hiện một datetime bù đắp-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>) 

Sau đó bạn có thể so sánh cả hai datetimes bù đắp-aware w/o rắc rối.

Hơn nữa, bạn có thể chuyển đổi datetime bù đắp để bù giờ datetime bằng cách loại bỏ thông tin múi giờ, sau đó nó có thể được so sánh w/bình thường datetime.datetime.now(), dưới utc.

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

USE_TZTrue 'theo mặc định' (trên thực tế đó là False theo mặc định, nhưng settings.py tập tin được tạo ra bởi django-admin.py startproject đặt nó vào True), sau đó nếu DB của bạn hỗ trợ lần múi giờ nhận thức, giá trị của mô hình thời gian liên quan các trường sẽ là nhận thức về múi giờ. bạn có thể tắt tính năng này bằng cách đặt USE_TZ=False (hoặc chỉ cần xóa USE_TZ=True) trong cài đặt.

+4

Django không lưu trữ thời gian nhận biết cho TimeField, nó chỉ làm cho DateTimeField. Nó thực sự gây phiền nhiễu, vì đối tượng datetime.time python không hỗ trợ TZINFO giống như các đối tượng datetime.datetime. Tôi tự hỏi họ sẽ sửa chữa nó trong bản phát hành tiếp theo. Btw tôi đã thử nghiệm nó trên máy chủ cơ sở dữ liệu postres 9.1. – tejinderss

+0

@tejinderss: 'datetime.time' là sai. Không có thời điểm để lưu trữ múi giờ 'Châu Á/Thượng Hải'' nếu bạn không biết ngày tháng (chênh lệch có thể khác nhau trong cùng một thời điểm nhưng vào những ngày khác nhau). – jfs

+0

@okm: 'make_aware (datetime.now(), get_default_timezone())' thất bại nếu 'get_default_timezone()' khác với múi giờ địa phương của bạn (nó phải là nhưng nó không phải là toàn bộ đáng tin cậy). Chỉ cần sử dụng 'timezone.now()' thay vào đó (nó là nhận biết múi giờ nếu 'USE_TZ' là' True'). – jfs

Các vấn đề liên quan