この記事について
この記事では、Python で現在日時を、時差考慮の上での取得方法について綴ったものです。
標準モジュール (datetime
) のみの使用で、Python2 でも Python3 でも動く方法をメモしました。
datetime
モジュールの色々なメソッドやオブジェクトの詳しい説明は省いています。
きっかけ
Python で Web アプリを実装し、Heroku 上で動かそうとしていたときのこと。
ある機能の実装をしようとし、現在日時の取得の必要が。
単に現在時刻を取得しようとすると、Heroku サーバのシステム時刻が取得される。
Heroku サーバでは、+00:00 (UTC) でシステム時刻が動いている。
では、日本でアプリを動かしたとき、単に Heroku のシステム時刻が使われたらどうなるか。
アプリで機能を動かし、時刻取得をしたとき、日本時間 12:00 とします。
すると、Heroku のシステム時刻は 3:00。
日本時間は 12:00 だけど、アプリでは 3:00 として処理が進んでしまう。
んー、これじゃ良くない・・・。(カレンダー、リマインダーならなおさら。)
単に 9時間足してやればすぐ解決だが、せっかくだからサーバのタイムゾーン設定に依存せずに正確な日時が帰ってくるようにしたいな・・・。
手順
先に、とりあえず動くコード全体から示してしまいます。
import datetime
# UTC (協定世界時) の時刻を取得
time_now_utc = datetime.datetime.utcnow()
print(time_now_utc)
# 2020-10-10 14:51:22.910110
# UTC より、日本は 9時間進んでいる
time_dt_ja = datetime.timedelta(hours=9)
print(time_dt_ja)
# 9:00:00
# UTC に 9時間足してやれば、日本時間になる
time_now_ja = time_now_utc + time_dt_ja
print(time_now_ja)
# 2020-10-10 23:51:22.910110
1. まずは UTC (協定世界時) の取得
datetime.datetime.utcnow()
で日時を取得してやると、稼働マシンのタイムゾーンが日本でもイギリスでもアメリカでも、同じ結果 (UTC) が得られます。
(datetime.datetime.now()
だと、稼働マシンのタイムゾーン設定によって結果が変わってきてしまいます。)
まずはこれで稼働マシンのタイムゾーン設定の違いを埋めます。
time_now_utc = datetime.datetime.utcnow()
print(time_now_utc)
# 2020-10-10 14:51:22.910110
type(time_now_utc)
# <class 'datetime.datetime'>
ここではdatetime
オブジェクトが得られます。
2. 次に時差を適用する計算の準備
timedelta
オブジェクトの準備をします。
datetime
オブジェクトは時刻情報のオブジェクトで、timedelta
は時間情報のオブジェクトです。
time_dt_test = datetime.timedelta(days=1, seconds=1, microseconds=1, milliseconds=1, minutes=1, hours=1, weeks=1)
print(time_dt_test)
# 8 days, 1:01:01.001001
type(time_dt_test)
# <class 'datetime.timedelta'>
このような形で日 (週、日) や時間 (時間、分、秒) を指定してやると、日と時間情報に変換してくれます。
3. 最後に計算
datetime
オブジェクトとtimedelta
オブジェクトは、+
-
で演算できます。
UTC に 9時間を足してやることで日本時間になるので、
time_now_ja = time_now_utc + time_dt_ja
print(time_now_ja)
# 2020-10-10 23:51:22.910110
あとは、適宜datetime
のメソッドを使うなりしておしまい。
print(time_now_ja.strftime("%Y年 %m月 %d日"))
# 2020年 10月 10日
strftime()
についてですが、%Y
, %d
, %m
だけでなく、色々な書式コードがあるようです。
詳しくは公式ドキュメントを参照
https://docs.python.org/ja/3/library/datetime.html#strftime-strptime-behavior
余談
公式ドキュメントによると、UTC の取得はdatetime.datetime.utcnow()
よりも
datetime.datetime.now(datetime.timezone.utc)
の方が推奨されているようです。
https://docs.python.org/ja/3/library/datetime.html
ただ、Python2 ではtimezone
オブジェクトが無いようです。
(でも、タイムゾーン関係はtimezone
オブジェクトを使っての実装の方が多分ずっとスマート。)