django 1.4 - không thể so sánh ngày giờ bù đắp và nhận biết bù đắp


85

Tôi đang trong quá trình di chuyển ứng dụng từ django 1.2 sang 1.4.

Tôi có một đối tượng nhiệm vụ hàng ngày chứa thời gian trong ngày mà nhiệm vụ đó sẽ đượ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 nhiệm vụ có còn được yêu cầu hoàn thành hôm nay hay không, tôi có 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

Điều này hoạt động tốt dưới 1,2, nhưng dưới 1,4, tôi gặp 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 mắc lỗi này.

Tôi đã thử làm cho múi giờ timeDue nhận biết bằng cách thêm pytz.UTC làm đối số, nhưng điều này vẫn gây ra lỗi tương tự.

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

Câu trả lời:


168

Kiểm tra tài liệu kỹ lưỡng để biết thông tin chi tiết.

Thông thường, sử dụng django.utils.timezone.nowđể tạo ngày giờ hiện tại có nhận biết bù trừ

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

django.utils.timezone.make_awaređể tạo ra một ngày giờ có nhận biết bù trừ

>>> 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 lịch ngày nhận biết bù trừ có rắc rối.

Hơn nữa, bạn có thể chuyển đổi ngày giờ chờ bù đắp thành ngày giờ bù trừ bằng cách loại bỏ thông tin múi giờ, sau đó nó có thể được so sánh với w / normal 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' (thực ra là Falsetheo mặc định, nhưng settings.pytệp được tạo bằng cách django-admin.py startprojectđặt nó thành True), thì nếu DB của bạn hỗ trợ thời gian nhận biết múi giờ, giá trị của các trường mô hình liên quan đến thời gian sẽ nhận biết múi giờ. bạn có thể vô hiệu hóa nó bằng cách cài đặ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ưu trữ cho DateTimeField. Nó thực sự khó chịu, vì đối tượng datetime.time của python hỗ trợ TZINFO giống như các đối tượng datetime.datetime. Tôi tự hỏi họ sẽ sử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

@tejinderss: datetime.timesai. Không có điểm nào để lưu trữ 'Asia/Shanghai'múi giờ nếu bạn không biết ngày (chênh lệch utc có thể khác nhau cho cùng một thời điểm nhưng vào các ngày khác nhau).
jfs

@okm: make_aware(datetime.now(), get_default_timezone())không thành công nếu get_default_timezone()khác với múi giờ địa phương của bạn (đúng như vậy nhưng nó không hoàn toàn đáng tin cậy). Chỉ cần sử dụng timezone.now()thay thế (nó là múi giờ nhận biết nếu USE_TZTrue).
jfs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.