Djangoの1.4以降で追加されたタイムゾーンサポートのことがよくわかってなかったのでドキュメントを読みつつ軽くまとめてみました。
Time zones | Django documentation | Django
タイムゾーンサポートの有効化
settings.pyのUSE_TZにTrue/Falseで設定する。
デフォルトでは有効。
概要
タイムゾーンサポートが有効化されていると、日付時刻はデータベースにUTCで保存される。
その際にはDjangoは内部的にtime-zone-awareなdatetimeオブジェクトを使い、テンプレート等で表示するときにユーザーのタイムゾーンに直される。
複数タイムゾーンのユーザーに時刻を表示するときやサマータイム(Daylight Saving Time)対応等で便利。
naiveとaware
Pythonのdatetime.datetimeはnaive(タイムゾーン情報を持っていない)とaware(タイムゾーン情報を持っている)の2種類に区別される。
詳細はPythonのドキュメントより
time や datetime 型のオブジェクト d は naive にも aware にもできます。 d は d.tzinfo が None でなく、かつ d.tzinfo.utcoffset(d) が None を返さない場合に aware となります。 d.tzinfo が None の場合や、 d.tzinfo は None ではないが d.tzinfo.utcoffset(d) が None を返す場合には、 d は naive となります。
tzinfoはタイムゾーンや夏時間の計算に使われる、datetime.tzinfoクラスのサブクラスのインスタンス。
DBレイヤーがnaive datetimeを受け取ると、default time zone(settingsのTIME_ZONE)に従ってUTCに変換しようとする。しかしサマータイムによる曖昧さなどの理由により例外を投げたり不正確な結果になったりするのでnaive datetimeを使うのは良くない。
UTCを扱う
開発者は常にUTCのaware datetimeを扱うべき。
現在時刻を取得するときにはdatetime.datetime.now()ではなくdjango.utils.timezone.now()を使用する。(USE_TZの設定によって適切なdatetimeを返してくれる)
$ python manage.py shell >>> from django.conf import settings >>> settings.USE_TZ True >>> import datetime >>> from django.utils import timezone >>> timezone.is_aware(datetime.datetime.now()) False >>> timezone.is_aware(timezone.now()) True
default time zoneとcurrent time zone
default time zone: settingsのTIME_ZONEで指定されたタイムゾーン
current time zone: 表示に使われるタイムゾーン
current time zoneがセットされていない場合はdefault time zoneが表示につかわれる。
djangoがユーザーから自動的に判定してcurrent time zoneを設定したりはしないので、ユーザーのタイムゾーンに合わせて表示するにはdjango.utils.timezone.activate(timezone)によってcurrent time zoneをセットする必要がある。
(ドキュメントのこの辺りにタイムゾーン設定のサンプルコードがある。)
pytz
Djangoはpytzがインストールされている場合pytzを利用するため、インストールすることが強く推奨されている。
pip install pytz
Fixturesにおけるdatetime
aware(UTCオフセットを含んでいる)
"2011-09-01T13:20:30+03:00"
naive
"2011-09-01T13:20:30"
formでのdatetime
Djangoが入力をawareなdatetimeに変換してcleaned_dataに入れてくれたりする。
テンプレートでのdatetime
タイムゾーンに関するタグやフィルタが色々ある。
——–
サマータイムのない日本人にはサマータイム問題ってあんまり実感わかないですね。。
必要ないなら使わないほうがシンプルな気もするけどせっかくだから使えるようになっておきたい。