環境
- Django 3.0.3 Time zones | Django documentation | Django
タイムゾーンを設定
settings.pyでUSE_TZ
とTIME_ZONE
を設定する必要があります。
settings.py
USE_TZ = True # タイムゾーンを使う
TIME_ZONE = "Asia/Tokyo" # タイムゾーンを日本時間にする
modelのDateTimeFieldから取り出してタイムゾーンの時刻を取得
Djangoではローカライズした時刻で保存してもデータベースにはUTCの時刻で保存されます。
from models import Product
from django.utils.timezone import localtime
product = Product.objects.get(pk=1)
print(product.created_at)
# 2021-01-21 10:26:06.994428+00:00
print( localtime(product.created_at) )
# 2021-01-21 10:26:06.994428+09:00
UTCで保存されるのは、複数のタイムゾーンを利用するときに柔軟に時刻の変換ができるからです。
pythonで時刻を扱うときの概念、
- native(タイムゾーンなしの時刻)
- aware(タイムゾーンありの時刻)
が影響しています。
これらの概念は以下の記事が参考になります。
基本的な日付型および時間型
【Django】naive timeをaware timeに変換する方法
viewでタイムゾーンの時刻を取得
from django.utils import timezone
from django.utils.timezone import localtime
print( localtime(timezone.now()) )
# 2021-01-21 10:26:06.994428+09:00
localtime() で時刻をローカライズ
django.utils.timezone
で時刻を呼びたしただけではローカライズされていません。
from django.utils import timezone
print( timezone.now() )
# 2021-01-21 01:26:06.994401+00:00
settings.py
のTIME_ZONE
で設定した時刻を取得するには、django.utils.timezone.localtime
を使ってローカライズされた時刻に変換する必要があります。
pythonのdatetimeはローカライズできない
当たり前ですけど、これはエラーになります。
from datetime import datetime
print( datetime.now())
# 2021-01-21 10:43:12.858566
print( localtime(datetime.now()))
# localtime() cannot be applied to a naive datetime
templateでタイムゾーンの時刻を取得
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils import timezone
class DashboardIndexView(LoginRequiredMixin, generic.TemplateView):
""" ダッシュボード """
template_name = 'dashboards/index.html'
raise_exception = True # 403ページの表示
def get_context_data(self, **kwargs):
now = timezone.now()
print( now )
# 2021-01-21 01:53:31.005940+00:00
context = super().get_context_data(**kwargs)
context['now'] = now
return context
dashboards/index.html
{{ now }}
<!-- 2021年1月21日10:53 -->
テンプレート側でタイムゾーンの時刻を取得する場合はdjango.utils.timezone
でローカライズする必要はありません。