0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

djangoで「TypeError: can't subtract offset-naive and offset-aware datetimes」というエラー

Last updated at Posted at 2023-06-21

結論

datetime.datetime型同士の演算をするときに、日時表現が異なるもので演算を行ったために発生するエラーです。make_naivemake_aware関数を使用して表現をそろえることで解決できます。

エラーを再現

以下のコードを実行するとエラーが発生します。

.py
import datetime

dt1 = datetime.datetime.now()
dt2 = datetime.datetime.now(datetime.timezone.utc)

dt2 - dt1
TypeError: can't subtract offset-naive and offset-aware datetimes

原因

以下の記事が参考になります。

どうやら、datetime.datetime型の変数はawarenaiveという日時表現があるようです。この表現が異なるもの同士を演算することができないことから起きるエラーのようでした。

aware: タイムゾーン、サマータイムも含めた日時表現
naive: タイムゾーン、サマータイムは含めない日時表現

実際にエラーが発生したコードの変数をprintしてみるとわかりやすいです。

.py
import datetime

dt1 = datetime.datetime.now()
dt2 = datetime.datetime.now(datetime.timezone.utc)

print(dt1) # naive表現
print(dt2) # aware表現
2023-06-21 05:47:29.994050
2023-06-21 05:47:29.994103+00:00

これがdjangoで起きる原因

私も全てを理解できているわけではないうえで書くことになる点、ご了承ください。djangoではモデルの日時型フィールドはaware表現のものを扱っているように思います。それゆえ、例えばdatetime.datetime.now()などで取得した変数と演算すると、異なる表現同士を演算しようとしてエラーが発生することになります。

解決策

表現をそろえることで解決できます。
djangoには表現をそろえる関数であるmake_naivemake_awareがあるので、それを使用していきます。

.py
import datetime
from django.utils.timezone import make_naive

dt1 = datetime.datetime.now()
dt2 = datetime.datetime.now(datetime.timezone.utc)
# ともにnaive表現になる
dt1 - make_naive(dt2)

上記のコードだとdt2がnaive表現になるので、両方ともnaive表現で演算できるということになります。

補足

そもそも、datitime.datetime型同士を演算するとどのような結果が返ってくるのか。これについては以前の私の記事が参考になります。

以上です。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?