はじめに
pythonにおいて時刻を扱うdatetiem.datetime
とdatetime.time
オブジェクトにはnaive
とaware
という概念があります。
これは、生成されたオブジェクトがタイムゾーンの情報を持っているかどうかを示す属性値であり、タイムゾーンの情報を持っていればaware
, なければnaive
になります。
このawareとnaiveという部分で躓くことが個人的に多かったので、知識を整理する意味でまとめておこうと思います。
概要〜naiveとawareとは
naiveとawareの区別自体は上記の通りで、タイムゾーンの情報を含んでいるかどうかによる。
タイムゾーン情報を含んでいるインスタンスを出力した場合には、+-xx:yy
のような形式で世界標準時との差異が表示される。
なお、naive型とaware型の組み合わせに対しては、等号・不等号での比較ができない(naive同士・aware同士なら比較可能)。
# 変数now_naiveがnaive型の場合
print(now_naive)
>> 2021-11-16 10:05:46.268496
# 変数now_awareがaware型の場合
print(now_aware)
>> 2021-11-16 10:05:46.268704+09:00
タイムゾーン情報の取得
aware型のインスタンスはtzinfo
という属性値を持っており、この値を参照することでタイムゾーンを取得することができる。
print(now_aware.tzinfo)
>> JST
# JSTは日本標準時の意味
# naive型のtzinfoはNoneになる
print(now_naive)
>> None
作成されるインスタンスのタイムゾーンの有無
datetime.datetime.now()
で生成されるインスタンスは基本的にnaive
型になるが、now()の引数としてtimezoneインスタンス(後述)を指定することでタイムゾーン情報を持ったaware
なインスタンスを作成することができる。
import datetime
naive = datetime.datetime.now()
print(naive)
>> 2021-11-16 10:27:22.231630
print(naive.tzinfo)
>> None
aware_utc = datetime.datetime.now(dateteme.timezone.utc)
# datetime.datetime.utcは世界標準時の情報を持ったitmezoneインスタンス
print(aware_utc)
>> 2021-11-16 01:27:56.635804+00:00
print(aware_utc.tzinfo)
>> UTC
naive型のインスタンスの時刻は世界標準時ではなく現地時刻に合わせたものになることに注意。
例えばこの記事は日本で書いているので、naive型の変数の時刻はtzinofo="JST"
のものと同じになる(もちろんtimezone情報は持っていないが)。
タイムゾーンの指定方法
awareなインスタンスを作る方法の一つとして上記のようにdatetime.timezone.utc
をnow()の引数にする方法があるが、これでは世界標準時に基づくインスタンスしか作成できない。
タイムゾーンを任意のものに変更するための方法として、世界標準時から変換する、datetime()の引数として指定する、now()の引数として指定する、の3種類がある。
世界標準時から変更する
astimezone()
メソッドを用いることで、ローカルのタイムゾーンに変更することができる。
now_utc = datetime.datetime.now(datetime.timezone.utc)
print(utc_now)
>> 2021-11-16 01:27:56.635804+00:00
now_jst = now_utc.astimezone()
print(now_jst)
>> 2021-11-16 01:27:56.635804+09:00
世界標準時との差異は+00:00
から+09:00
に変更されているものの、時刻自体は2021-11-16 01:27:56.635804
で変更されていないことに注意。
datetime()の引数として指定する
datetime()の引数として年月日や時刻などとともにタイムゾーンの情報を与えることで、awareなインスタンスが作成される。
import datetime
from zoneinfo import Zoneinfo
now_jst = datetime.datetime(2020, 1, 1, tzinfo=Zoneinfo("Asia/Tokyo"))
# タイムゾーン情報はキーワード引数の形式で設定
print(now_jst)
>> 2020-01-01 00:00:00+09:00
print(now_jst.tzinfo)
>> Asia/Tokyo
nowの引数として設定する
now()はdatetime.timezone.utc以外にも、datetime.timezoneオブジェクトを引数として受け取ることが可能。
utc
以外の引数に関しては地名や記号を用いるのではなく、以下のようにdatetime.timedelta
オブジェクトを用いて世界標準時からの差異を指定する。
now_jst = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9)))
print(now_jst)
>> 2020-01-01 00:00:00+09:00
print(now_jst.tzinfo)
>> UTC+09:00