2018/12/06更新

[Python] datetimeでタイムゾーンを扱う(pytz利用、UTC/JSTの変換、など)

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
Pythonの日付でタイムゾーンを扱う機会があったので、今日はそれをブログに書きたいと思います。



目次




pytzの導入

Pythonの日付処理でタイムゾーンを扱う場合、pytzというライブラリを使うと便利です。インストールします。
$ pip install pytz



タイムゾーンを指定しない場合の問題点

タイムゾーンを考慮せず日時を生成すると、実行環境(=パソコンやサーバー)のタイムゾーン設定に合わせて、日付が表示されます。
from datetime import datetime

# パソコンのタイムゾーン設定が Asia/Tokyo の場合の例
print(datetime.now())

# 出力例:2018-12-06 00:59:48.677942
この場合には、パソコンのタイムゾーンが日本なので日本時間を表示をしていますが、出力された時間だけをみると、どのタイムゾーンの時間かはわかりません。

また、タイムゾーンを表示するようにフォーマットを指定して日付文字列を表示しても、タイムゾーンは表示されません。
from datetime import datetime

# フォーマット「%z」を用いて、タイムゾーン表示をする
print(datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f%z'))

# 出力例:2018-12-06T01:05:39.016152        # <- タイムゾーンが表示されない.
小さなプログラムであれば、これで問題ないことも多いですが、他システムとデータ連携をする場合(例:Webフロントに日付をサーバーから返却する、など)、この日付形式では困ります。どのタイムゾーンなのかを判断できません。

それだと困るので、タイムゾーン付きで日付を表現したいところです。



datetimeモジュールでタイムゾーンを扱う

タイムゾーンを日付処理で扱いたい場合、日付の生成時にタイムゾーンを指定します。
from datetime import datetime
from pytz import timezone

# タイムゾーンを指定して、日時を作成.
print(datetime.now(timezone('Asia/Tokyo')))

# 出力例:2018-12-06 01:02:06.516299+09:00
無事に+09:00とタイムゾーンの表示をすることができました。

また、生成済みの日時オブジェクトに対して、タイムゾーンを指定することもできます。
from datetime import datetime
from pytz import timezone

# 日付オブジェクトを作成(タイムゾーン指定なし).
now = datetime.now()

# 生成済みの日付オブジェクトに、タイムゾーン指定を追加する.
now = now.astimezone(timezone('UTC'))

# 表示する.
print(now)

# 出力例:2018-12-05 16:10:39.701882+00:00
このようにastimezoneメソッドを使うと、datetimeオブジェクト自体が指す日時は変えずに、タイムゾーンを設定できます。



JST/UTC変換を行う

上記の機能を用いることで、いろいろなタイムゾーンで、日付を表現できます。
from datetime import datetime
from pytz import timezone

# UTCで日付を作成する.
now = datetime.now(timezone('UTC'))
print(now)
# 出力例:2018-12-05 16:14:33.218561+00:00

# JSTに変換する.
now = now.astimezone(timezone('Asia/Tokyo'))
print(now)
# 出力例:2018-12-06 01:14:33.218561+09:00

# UTCに戻す.
now = now.astimezone(timezone('UTC'))
print(now)
# 出力例:2018-12-05 16:14:33.218561+00:00
これで、タイムゾーンを自由に扱えますね。



タイムゾーン付きの日付文字列をパースして読み込む

strptimeメソッドを用いて、タイムゾーンの情報も含めて読み込むことができます。
from datetime import datetime
from pytz import timezone

# タイムゾーン付きの日付文字列を生成.
now_str = datetime.now(timezone('Asia/Tokyo')).strftime('%Y-%m-%dT%H:%M:%S.%f%z')
print(now_str)
# 出力例:2018-12-06T01:21:17.118359+0900

# 上で生成した日付文字列を読み込む.
now2 = datetime.strptime(now_str, '%Y-%m-%dT%H:%M:%S.%f%z')
print(now2)
# 2018-12-06 01:21:17.118359+09:00
ここでは%zで、タイムゾーンを考慮した日付文字列の読み込みを行なっています。文字列のフォーマットはこちらをご参照ください。



補足1:pytzを使わずにタイムゾーンを扱う

datetimeパッケージにtimezoneモジュールがあり、それを使えば、pytzを使うことなくタイムゾーンを処理できます。
from datetime import datetime, timedelta, timezone

# JSTタイムゾーンを作成
jst = timezone(timedelta(hours=9), 'JST')

# JSTで、日付を作成
now = datetime.now(jst)
print(now)
# 出力例:2018-12-06 01:18:21.852966+09:00

# UTCで、日付を作成
now = datetime.now(timezone.utc)
print(now)
# 出力例:2018-12-05 16:18:21.854607+00:00
これはこれで、お手軽でいいかなーと思います。



補足2:PCやサーバーのタイムゾーン設定を確認する

MacやLinuxサーバーの場合、dateコマンドを実行すると、タイムゾーンを確認することができます。
$ date
2018年 12月  5日 水曜日 15:55:16 UTC
この場合、UTCであることがわかります。



最後に

今日はタイムゾーンを扱うお話でした。タイムゾーンを扱えるようになると、プログラミングのスキルもまた一歩成長したという感じがあります!

最後になりますが本ブログでは、Python、PHP、フロントエンド、サーバー、インフラ、Swift、Node.js、Java、Linux、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時の、解決の糸口に!」そんな目標でブログを書き続けています。ぜひ、本ブログのRSSTwitterをフォローして貰えたら嬉しいです ^ ^

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。