django1.4-オフセットなしの日時とオフセット対応の日時を比較できません


85

アプリケーションをdjango1.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

両方の比較句がこのエラーをスローします。

引数としてpytz.UTCを追加して、timeDueタイムゾーンを認識させようとしましたが、それでも同じエラーが発生します。

タイムゾーンに関するいくつかのドキュメントを読みましたが、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_TZTrue「デフォルト」です(実際にFalseはデフォルトですが、に設定してsettings.py生成されたファイル)。DBがタイムゾーン対応の時間をサポートしている場合、時間関連のモデルフィールドの値はタイムゾーン対応になります。設定で設定(または単に削除)することで無効にできます。django-admin.py startprojectTrueUSE_TZ=FalseUSE_TZ=True


4
DjangoはTimeFieldの認識時間を保存せず、DateTimeFieldに対してのみ保存します。Pythonのdatetime.timeオブジェクトはdatetime.datetimeオブジェクトと同じようにTZINFOをサポートしているため、非常に煩わしいです。彼らは次のリリースでそれを修正するのだろうか。ところで、私はpostres9.1データベースサーバーでそれをテストしました。
tejinderss

@tejinderss:datetime.time間違っています。'Asia/Shanghai'日付がわからない場合、タイムゾーンを保存する意味はありません(utcオフセットは、同じ時間でも異なる日付でも異なる場合があります)。
jfs 2015

@okm:ローカルタイムゾーンと異なるmake_aware(datetime.now(), get_default_timezone())場合get_default_timezone()は失敗します(そうあるべきですが、完全に信頼できるわけではありません)。timezone.now()代わりに使用してください(そうである場合はタイムゾーンに対応していUSE_TZますTrue)。
jfs 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.