1. ホーム
  2. python

[解決済み] django 1.4 - オフセット無視のデータタイムとオフセット考慮のデータタイムを比較できません。

2023-03-29 19:23:56

質問

私は、アプリケーションを django 1.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のタイムゾーンを認識させようとしましたが、これでも同じエラーが発生します。

timezones に関するドキュメントをいくつか読みましたが、timeDue の timezone を認識させる必要があるだけなのか、それとも私の db と既存のデータに根本的な変更を加える必要があるのか、混乱した状態になっています。

どのように解決するのですか?

確認 徹底的なドキュメント をご覧ください。

通常は 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() と比較できます。

>>> 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 によって生成されるファイルは django-admin.py startproject に設定します。 True ) を設定すると、DBがタイムゾーンを認識する時間をサポートしている場合、時間に関連するモデルフィールドの値はタイムゾーンを認識するようになります。 USE_TZ=False (を設定することで無効にできます(あるいは、単純に USE_TZ=True を削除することもできます。