LoginSignup
5
4

More than 3 years have passed since last update.

python/djangoで文字列からdatetimeに変換するときのtimezone設定

Last updated at Posted at 2019-10-08

めちゃくちゃ初歩的なミスを犯すところだったので戒めにメモしておきます。。。

背景

Twitter APIを用いて構築しているTwitterクローラで、デフォルト設定である1週間単位でツイートデータを収集していたが、1週間丸ごと取りに行くとデータ量的にクロールにかかる時間が長くなってしまう為、クロールしてくる期間を変更したい。
しかし、Standard Search APIには取得開始日時から特定の日時までのデータに絞るパラメータが存在していない為、APIの返り値から日付情報を抽出して比較する必要がある。
(厳密には、since_idはあるけど仕様が謎で使いづらい・・・)

問題

以下のように、django.utils.timezoneを用いてJSTで対象期間を定義し、APIの返り値をJSTに変換して比較しようとしていた。

import datetime
from django.utils import timezone

target_datetime = timezone.localtime(timezone.now()) - datetime.timedelta(days=4)

created_at = "Thu Oct 03 15:28:43 +0000 2019" #APIから抽出した日付文字列
created_at_datetime = timezone.make_aware(datetime.datetime.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y'), timezone.get_default_timezone())

if created_at_datetime > target_datetime:
以下省略

しかし、このやり方だと以下のように「UTC」の日時が「JST」に変換されないまま、「JST」のタイムゾーン情報だけが付与された形になっていた。

>>> created_at = "Thu Oct 03 15:28:43 +0000 2019"
>>> created_at_datetime = timezone.make_aware(datetime.datetime.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y'), timezone.get_default_timezone())
datetime.datetime(2019, 10, 3, 15, 28, 43, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)

解決方法

UTC文字列をJSTのdatetimeに変換するには以下の手順を踏む必要がある。

>>> created_at = "Thu Oct 03 15:28:43 +0000 2019"
>>> created_at_datetime_utc = datetime.datetime.strptime(created_at, '%a %b %d %H:%M:%S %z %Y')
>>> timezone.localtime(created_at_datetime_utc)
datetime.datetime(2019, 10, 4, 0, 28, 43, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)

なお、datetime同士の比較を行うだけの目的であればわざわざ変換しなくてもよしなに計算してくれる模様。

>>> created_at_datetime
datetime.datetime(2019, 9, 29, 20, 32, 44, tzinfo=datetime.timezone.utc)
>>> target_datetime
datetime.datetime(2019, 9, 29, 20, 32, 44, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
>>> created_at_datetime > target_datetime
True

>>> created_at_datetime
datetime.datetime(2019, 9, 29, 12, 32, 44, tzinfo=datetime.timezone.utc)
>>> target_datetime
datetime.datetime(2019, 9, 29, 20, 32, 44, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
>>> created_at_datetime > target_datetime
True

>>> created_at_datetime
datetime.datetime(2019, 9, 29, 10, 32, 44, tzinfo=datetime.timezone.utc)
>>> target_datetime
datetime.datetime(2019, 9, 29, 20, 32, 44, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
>>> created_at_datetime > target_datetime
False
5
4
1

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
5
4