Python

Python初学者向け:2つの日時オブジェクトの引き算をする方法

スポンサーリンク

 

この記事はこんな方におススメです
  • データ分析をはじめたいが、どのように学習を進めればよいかわからない方
  • データ分析の基本的な部分の全体像を把握しておきたい方
  • データ分析の勉強を始めたが、進め方に迷っている方

▶ 初学者向けにPythonを使ったデータ分析に役立つ記事を書いています

はじめに

今回は日時オブジェクトの引き算について基本から解説します。Pythonで日次オブジェクトの引き算をするときにうまくいかなかったことはありませんか?私はタイムゾーンの処理をした日時オブジェクトとタイムゾーンの概念を持たない日付型オブジェクトで演算をしているからかもしれません。基本から見ていきましょう。

環境

  • Windows10
  • Python 3.9.7
  • pandas 1.5.0
  • numpy: 1.23.3
  • matplotlib: 3.6.1

日時のオブジェクト

日時のオブジェクトは、それらがタイムゾーンの情報を含んでいるかどうかによって “aware” あるいは “naive” に分類されます。

aware オブジェクトはタイムゾーンや夏時間の情報のような情報を持っています。awareオブジェクトは他の aware オブジェクトとの引き算ができます。

naive オブジェクトは協定世界時 (UTC) や現地時間、タイムゾーンなどの情報を持ちません。また、naiveオブジェクトは他のnaiveオブジェクトとの引き算ができます。

つまり、日時のオブジェクトはaware, naiveの種類が揃っていないと引き算の演算ができません。

オブジェクトが Aware なのか Naive なのかの判断¶

日付のオブジェクトがaware、あるいは、naiveで揃っていないと引き算ができません。そのため対象のオブジェクトがaware、なのか、naiveなのかを判別する必要があります。

ここでは、その判別方法を見ていきましょう。
詳細はPythonの公式ドキュメントを参考にしてください。

  • date 型のオブジェクトは常に naive
  • time 型あるいは datetime 型のオブジェクトは aware か naive のどちらか

となります。次にtime型、datetime型がawareであるか、naiveであるかの判別方法を見ていきましょう。

time型オブジェクトのaware/naiveの判定

次の条件を両方とも満たす場合、 time オブジェクトtは aware です:

  1. t.tzinfo が None でない
  2. t.tzinfo.utcoffset(None) が None を返さない

どちらかを満たさない場合は、その time オブジェクトは naive です。
※簡易的にtzinfoをもっていればaware、持っていなければnaiveと考えていれば、多くの場合問題ありません。

datetime型オブジェクトのaware/naiveの判定

次の条件を両方とも満たす場合、 datetime オブジェクトd は aware です:

  1. d.tzinfo が None でない
  2. d.tzinfo.utcoffset(d) が None を返さない

どちらかを満たさない場合は、 datetime オブジェクト は naive です。
※簡易的にtzinfoをもっていればaware、持っていなければnaiveと考えていれば、多くの場合問題ありません。

aware なオブジェクトと naive なオブジェクトの区別は timedelta オブジェクトにはあてはまりません。

日時オブジェクトの引き算

既に説明したように、日時のオブジェクトはaware, naiveの種類が揃っていないと引き算の演算ができません。そのため、日時のオブジェクトの比企さんの演算は、次のいずれかになります。

  • awareオブジェクト同士での引き算
  • naiveオブジェクト同士での引き算

日次のオブジェクトがawareであるか、naiveであるかの判定方法は既に解説したので、aware⇔naiveの変換ができれば、aware同士の演算、naive同士の演算をすることができます。

aware同士で引き算をする

簡単な例でみていきましょう。まず、日時のオブジェクトを2つ作ります。

import datetime

dt1 = datetime.datetime(2023,5,5,10,00,00) #naive
dt2 = datetime.datetime(2023,5,5,19,00,00,
                        tzinfo=datetime.timezone(datetime.timedelta(hours=9))) #aware

print(dt1)
print(type(dt1))
print(dt1.tzinfo)

print('-'*10)

print(dt2)
print(type(dt2))
print(dt2.tzinfo)

dt1はtzinfoを持たないのでnaive, dt2はawareです。dt1とdt2をそのまま引き算すると、エラーとなります。やってみましょう。

ここでは、dt2をnaiveにして計算してみましょう。

# dt2のtzinfoにNoneを与えてnaiveにして計算
dt2 = dt2.replace(tzinfo=None)
dt2 - dt1

今度はうまくいきました。dt2のtzinfoをNoneとしたので、2023年5月5日19時00分として扱われます。dt1が2023年5月5日10時00分なのでその差は9時間です。計算結果が32400秒なのでちょうど、9時間ですね。

naive同士で引き算をする

もう一度、dt1とdt2を作り直します。

import datetime

dt1 = datetime.datetime(2023,5,5,10,00,00) #naive
dt2 = datetime.datetime(2023,5,5,19,00,00,
                        tzinfo=datetime.timezone(datetime.timedelta(hours=9))) #aware

print(dt1)
print(type(dt1))
print(dt1.tzinfo)

print('-'*10)

print(dt2)
print(type(dt2))
print(dt2.tzinfo)

d1はnaive, dt2がawareになっています。今度はdt1をawareにして計算してみましょう。先ほどと同様にreplaceを使います。コントはtzinfoにタイムゾーンの情報を指定します。ここではUTCにしましょう。

# dt1のタイムゾーンにUTCを指定する
dt1 = dt1.replace(tzinfo=datetime.timezone.utc)

これでdt1,dt2ともにawareとなりました。

dt1:UTCで2023年5月5日10時00分
dt2:JSTで2023年5月5日19時00分
※dt2はUTC+9hourとしているのでJSTとしています

この差分を計算してみましょう。

dt2 - dt1

JSTの2023年5月5日19時00分は、UTCの2023年5月5日10時00分なので、差がない、という結果となるのですね。

スポンサーリンク

 

まとめ

今回は日時オブジェクトの差分について基本から解説しました。日時オブジェクトにはnaiveとawareがあり、これらが揃っていないと差分を計算することができません。naiveとawareは、tzinfoを持っているかどうかで判別できます。

awareとnaiveの変換は次のようにします。

  • aware→naiveはreplaceを使って、tzinfoにNoneを指定
  • naive→awareはreplaceを使って、tzinfoにタイムゾーンを指定

コメント

タイトルとURLをコピーしました