日付を扱うとき、ある日付が他の日付の前なのか後なのか知りたいことがよくあります。
日付を比較することで、これらの答えを得ることができます。
この記事では、Pythonの datetime
モジュールを使って、素朴な(タイムゾーン情報なしの)日付と意識した(タイムゾーン情報ありの)日付を作成し比較する方法を学びます。
日付を比較するために、Pythonの比較演算子を使用します。
Note: datetime
モジュールには、 datetime.datetime
と datetime.date
という2つの日付オブジェクトを生成するメソッドがあります。
比較は、同じクラスから作成されたオブジェクトに対してのみ行うことができます。
datetime.datetime.now() >= datetime.date.today()
これは TypeError
という結果になります。
TypeError: can't compare datetime.datetime to datetime.date
タイムゾーンナイブのデータタイムの比較
まず、タイムゾーンの情報を持たない単純な日付の比較から始めましょう。
まず、 datetime
モジュールをインポートします。
from datetime import datetime, date
次に、比較する日付をいくつか作ってみましょう。
date1 = date(1995, 3, 20)
date2 = date(2020, 1, 1)
dob_a = datetime(1995, 3, 20)
dob_b = datetime(2020, 1, 1)
これらのオブジェクトを比較するのは、例えば整数を比較するのと同じくらい簡単です。
ある日付が他の日付より小さいのは、その時刻が他の日付より先である場合です。
この場合、date1
は date2
よりも時間が古いので、より小さい (<
) と見なされます。
print("date1 comes before date2?", date1 < date2)
print("date1 comes after date2?", date1 > date2)
print("date1 is equal to date2?", date1 == date2)
この結果、次のようになります。
date1 comes before date2? True
date1 comes after date2? False
date1 is equal to date2? False
さて、このロジックをフロー制御の文に組み込むのが一般的でしょう。
if dob_a > dob_b:
print("person a is older than person b")
else:
print("person b is older than person a")
この結果は
person b is older than person a
タイムゾーンを考慮したデータタイムの比較
タイムゾーンは物事を少し複雑にしますが、ありがたいことに、まったく同じロジックを適用して比較することができます。
唯一の違いは、タイムゾーンを意識した日付、つまりタイムゾーンに関する追加情報を持つ日付を扱うということです。
from datetime import datetime
import pytz
# Create timezone objects for different parts of the world
tz_ny= pytz.timezone('America/New_York')
tz_lon = pytz.timezone("Europe/London")
# Year, Month, Day, Hour, Minute, Second
datetime = datetime(2010, 4, 20, 23, 30, 0)
# Localize the given date, according to the timezone objects
date_with_timezone_1 = tz_ny.localize(datetime)
date_with_timezone_2 = tz_lon.localize(datetime)
# These are now, effectively no longer the same *date* after being localized
print(date_with_timezone_1) # 2010-04-20 23:30:00-04:00
print(date_with_timezone_2) # 2010-04-20 23:30:00+01:00
print(date_with_timezone_1 == date_with_timezone_2)
このコードを実行すると、次のような結果が得られます。
False
一方、この文は
print(date_with_timezone_1 > date_with_timezone_2)
という結果になります。
True
さて、この結果は少し奇妙に感じられるかもしれません。
この2つの時刻を比較しているのです。
2010-04-20 23:30:00-04:00 # date_with_timezone_1
2010-04-20 23:30:00+01:00 # date_with_timezone_2
直感的には、 date_with_timezone_2
は date_with_timezone_1
よりも大きいように見えます。
しかし、ここで localize()
関数がどのように動作するのかを見てみましょう。
ここでは、 pytz
ライブラリを使用して、素朴な日付を認識できるようにしました。
ニューヨークのタイムゾーンオブジェクト (tz_ny
) と、ロンドンのタイムゾーンオブジェクト (tz_lon
) を作成しました。
そして、タイムゾーンの情報を datetime
オブジェクトに注入するために、 localize()
関数を実行して、その結果を date_with_timezone_1
と date_with_timezone_2
に詰め込みました。
localize()` に 11:30PM と入力すると、ニューヨークの 11:30PM とロンドンの 11:30PM をそれぞれ表す日付時刻が作成されます。
ニューヨークの11:30PMからロンドンの11:30PMになるには、4時間追加する必要があります。
ニューヨークが11:30PMになるには、ロンドンが11:30PMになるより多くの時間が経過しています。
したがって、ニューヨークの午後11時30分に対応する日時は、ロンドンの午後11時30分に対応する日時より大きくなります。
このようにタイムゾーンを扱う場合は、この挙動を念頭に置いてください。
ただし、注意すべきは、認識された日付と素朴な日付を比較すると、エラーになることです。
date_with_timezone = tz_ny.localize(datetime)
print(datetime == date_without_timezone)
これは次のようなエラーになります。
TypeError: can't compare offset-naive and offset-aware datetimes
つまり、datetimeオブジェクトを比較するには、両方のオブジェクトがnaiveかawareのどちらかでなければならないのです。
結論
この記事では、Pythonでタイムゾーンを考慮した日付とタイムゾーンを考慮しない日付を比較する方法について説明し、日付を比較する際に遭遇しうる落とし穴と可能な回避策についても見てきました。
もし質問や貢献があれば、以下のコメント欄に残してください。