DjangogirlsTutorialに出てくるtimezone.nowの秘密

C98d379da6e5517afff697a6c5615e68?s=47 mizzsugar
November 16, 2019

 DjangogirlsTutorialに出てくるtimezone.nowの秘密

C98d379da6e5517afff697a6c5615e68?s=128

mizzsugar

November 16, 2019
Tweet

Transcript

  1. DjangogirlsTutorialに出てくる timezone.nowの秘密 2019/11/16 Djangogirls @mizzsugar0425

  2. お前、誰よ • みずきと申します。 • やっていること↓ ◦ 昼:データ分析のデータ基盤のデータマネジメント (GCP: 特にBigQuery) ◦

    夜:PythonでWebアプリ開発(Pyramid, PostgreSQL, Nuxt.js, TypeScript) ◦ つい最近まで仕事で Djagoいじってたので趣味で Django触ったりもします ◦ Twitter -> @mizzsugar0425 • コーヒーと自転車が好き
  3. DjangogirlsTutorialの復習をしていたときのこと

  4. しれっと使ってるdjango.utils.timezone.now from django.conf import settings from django.db import models from

    django.utils import timezone class Post(models.Model): author = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE) title = models.CharField(max_length=200) text = models.TextField() created_date = models.DateTimeField(default=timezone.now) published_date = models.DateTimeField(blank=True, null=True) def publish(self): self.published_date = timezone.now() self.save() https://tutorial.djangogirls.org/ja/django_models/ timezone.nowは 現在の日時を返すよ
  5. なぜPython標準ライブラリの datetime.datetime.nowではないの? datetime.datetime.nowも 現在の日時を返すのに!!

  6. 秘密はここにあった! USE_TZ = True settings.py

  7. USE_TZ=Trueだとタイムゾーンサポートが有効 今19時 だよー 今10時 だよー

  8. タイムゾーンサポートがあるなら settings.pyで TIMEZONE = ‘Asia/Tokyo’と設定している場合・・・ • テンプレート上で日本時間を表示してくれて便利! • settings.pyのTIMEZONEを変更したらその場所の現地時間を表示 •

    複数のタイムゾーンを使う場合、どのタイムゾーンの時間を表示するか設定す ればどのタイムゾーンの時間を表示するかそれぞれ振り分けてくれる※ ※公式ドキュメントにタイムゾーンを選択して表示するための実装例があります ↓ https://docs.djangoproject.com/ja/2.2/topics/i18n/timezones/#selecting-the-current-time-zone
  9. 内部ではどうなっているの? >>> from django.contrib.auth.models import User >>> from blog.models import

    Post >>> >>> author = User.objects.create(username='dummy', email='dummy@example.com') >>> post = Post.objects.create( author=author, title='dummy', text='dummy' ) >>> post.publish() # 日本時間で2019/10/10 19:00:00に実行 >>> post.published_date datetime.datetime(2019, 10, 10, 10, 0, 0, tzinfo=<UTC>) 19時じゃない! UTCって!? を実行したら・・・ python manage.py shell
  10. 前提知識:nativeとawareという概念 ざっくりPythonでは 日時を扱うdatetimeモジュールのdatetimeオブジェクトを • タイムゾーンなしのdatetimeオブジェクトはnative ex: datetime.datetime(2019, 10, 10, 19,

    0, 0) • タイムゾーンありのdatetimeオブジェクトはaware ex: datetime.datetime(2019, 10, 10, 19, 0, 0, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) と分けている もっと詳しい説明は公式ドキュメントで ↓ https://docs.python.org/ja/3/library/datetime.html#aware-and-naive-objects
  11. UTCとは • 協定世界時(Coordinated Universal Time)のこと • 今の世界で標準時として使っている時間のこと • 日本の場合だと、世界の標準時間より9時間早い https://wa3.i-3-i.info/word11831.html

  12. 内部的な話 使う場所 表示形式 表示例 (日本時間2019/10/10 19時を例に) テンプレート・フォーム 現地時間(日本なら日本時間) テンプレート:2019年10月10日 19時0分0秒

    フォーム: datetime.datetime(2019, 10, 10, 19, 0, 0, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) 内部の処理 UTC時間 datetime.datetime(2019, 10, 10, 10, 0, 0, tzinfo=<UTC>) データベース タイムゾーンなしの時間 (値としてはUTCでの時間) 2019-10-10 10:00:00 ※PostgreSQLだと 2019-10-10 10:00:00+00
  13. 1つのタイムゾーンでしか使わなくても • native -> awareに変換した際に意図しない値に変換してしまうバグを防げる • Djangoがawareなdatetimeオブジェクトを想定している処理でnativeなオブジェ クトを使うことによるバグを防げる • django-admin

    startprojectコマンドで作られるプロジェクトでタイムゾーンサ ポートありになっていることからもタイムゾーンサポートありの方がいいと主張し ていることがうかがえる
  14. datetime.datetime.nowの話に戻ると・・・ >>> from django.utils import timezone >>> import datetime >>>

    >>> from django.utils import timezone >>> >>> # nativeなdatetimeオブジェクト >>> datetime.datetime.now() datetime.datetime(2019, 11, 12, 18, 0, 39, 452139) >>> >>> # タイムゾーンがUTCであるawareなdatetimeオブジェクト >>> timezone.now() datetime.datetime(2019, 11, 12, 9, 0, 46, 708708, tzinfo=<UTC>)
  15. USE_TZ=Trueでnativeなオブジェクトを使うと RuntimeWarning: DateTimeField received a naive datetime * to while

    time zone support is active. Djangoから「タイムゾーンサポートが有効な時にnativeなdatetimeオブジェク トを使わないでください」と注意されます。 エラーやワーニングは意地悪じゃなくて 安全なシステムを作るための優しさで 出来ているよ。
  16. つまりdatetime.datetime.nowは使わない訳は タイムゾーンサポートが有効な設定をしているから 使っても動きはするけれども native -> awareの変換周りで苦労するやも

  17. まとめ • Pythonのdatetimeオブジェクトにはnativeとawareという概念があり、前者 がタイムゾーンなしで後者がタイムゾーンありの日時(ざっくり) • Djangoではタイムゾーンサポートを有効にした方が安全 • タイムゾーンサポートを有効にした場合、Djangoでは内部的な処理ではタ イムゾーンがUTCの日時を使い、画面やフォームで現地時間に柔軟に変 換できるようにしている

    • エラーやワーニングは意地悪じゃなくて優しさ
  18. ありがとうございました!