エラー
TypeError: can't compare offset-naive and offset-aware datetimes
Djangoで開発をしている時にこのエラーが出たので,その原因と対処法をメモしておきます.
原因
Pythonのdatetimeモジュールを使った時に出会ったエラーになります.
このモジュールには大きく2種類あります.
offset aware
UTCオフセット(例: +09:00)やタイムゾーン情報を含み,異なるタイムゾーン間での時刻計算が可能
offset naive
タイムゾーン情報を持たず,ローカル時間として解釈されるため,異なるタイムゾーン間での計算には適さない
これらはデータ操作するときに相容れることができないため,このエラーが発生します.
解決策
簡単な解決策として,片方に統一する必要があります.
# naiveからawareへ変換
naive_date = "2025-02-06T14:31:38.464Z"
aware_date = timezone.make_aware(naive_date)
# awareからnaiveへ変換
aware_date = "2025-02-06T14:31:38.464Z"
naive_date = timezone.make_naive(aware_date)
実装例
バリデーションでこの変換を活用するのもアリだと思います.
APIの動作確認でcurlとswaggerUIを使っていたのですが,どうやらswaggerUIのデフォルト値がnaiveだったためバリデーションエラーが出ていました.どちらも通して大丈夫なので上記のような場合は変換するように修正しました.
def validate_deadline(self, value):
if timezone.is_naive(value): # offset-naive なら変換
value = timezone.make_aware(value)
if value <= timezone.now():
raise serializers.ValidationError("締め切り日時は現在以降である必要があります。")
return value