note.nkmk.me

Pythonで経過時間や日時(日付・時刻)の差分を測定・算出

Posted: 2019-02-04 / Tags: Python, 日時処理

Pythonで経過時間を測定したり、2つの日時(日付・時刻)の差分(時間差)を算出するには、標準ライブラリのtimeモジュール、datetimeモジュールを使う。経過時間や時間差は秒数や日数で表すことができる。

ここでは以下の内容について説明する。

  • 経過時間を測定
  • 日時(日付・時刻)の差分(時間差)を算出
    • datetimeオブジェクトの引き算
    • dateオブジェクトの引き算
    • datetimeオブジェクトとdateオブジェクトの引き算
    • 現在時刻と特定の日時との時間差
  • 時間差を加減した日時を取得

秒数と分・時間・日数などとの相互変換については以下の記事を参照。

スポンサーリンク

経過時間を測定

timeモジュールのtime()関数を使うとUNIX時間(エポック秒)を浮動小数点数float型で取得できる。

import time

ut = time.time()

print(ut)
# 1549281692.9876952

print(type(ut))
# <class 'float'>

UNIX時間(エポック秒)はUTC(協定世界時)の1970年1月1日0時0分0秒からの経過秒数。datetimeオブジェクトなどと相互に変換できる。

time.time()の返り値は浮動小数点数float()で小数点以下にミリ秒マイクロ秒の情報を持つが、公式ドキュメントにあるようにその精度はシステムに依存するので注意。

時刻は常に浮動小数点数で返されますが、すべてのシステムが 1 秒より高い精度で時刻を提供するとは限らないので注意してください。
time.time() --- 時刻データへのアクセスと変換 — Python 3.7.2 ドキュメント

time.time()を利用すると、Pythonのプログラム内で経過時間を測定できる。

開始時のUNIX時間をtime.time()で取得して変数に格納し保持しておいて、経過時間を測定したいタイミングで再度UNIX時間を測定し差分を算出すると経過時間の秒数が求められる。

start = time.time()

time.sleep(3)

t = time.time() - start

print(t)
# 3.001929998397827

この例ではtime.sleep()で処理を一時停止している。

なお、コードの実行時間を計測するためのtimeitというモジュールもある。自動で繰り返し測定し平均を出したりしてくれるので、処理速度の検討といった目的にはtimeitのほうが便利。

単純に処理にかかった時間をログとして残しておきたいというような用途であればtime.time()を利用するのが適当。

測定結果の秒数を分や時間に変換したい場合は以下の記事を参照。

日時(日付と時刻)の差分(時間差)を算出

プログラム内で開始タイミングと終了タイミングを指定するのではなく、任意の2つの日時の差分(時間差)を算出したい場合はdatetimeモジュールを使う。

datetimeモジュールには日時(日付と時刻)を表すdatetime型、日付を表すdate型があるが、それらのオブジェクト同士を引き算して差分を求めると、時間差を表すtimedelta型のオブジェクトが生成される。

datetimeモジュールの基本的な内容については以下の記事を参照。

datetimeオブジェクトの引き算

datetimeオブジェクトの場合。

import datetime

dt1 = datetime.datetime(year=2017, month=10, day=10, hour=15)

print(dt1)
# 2017-10-10 15:00:00

print(type(dt1))
# <class 'datetime.datetime'>

dt2 = datetime.datetime(year=2019, month=1, day=1, hour=12)

print(dt2)
# 2019-01-01 12:00:00

td = dt2 - dt1

print(td)
# 447 days, 21:00:00

print(type(td))
# <class 'datetime.timedelta'>

timedeltaオブジェクトは日数、秒数、マイクロ秒数の情報を持ち、属性days, seconds, microsecondsでアクセスできる。また、total_seconds()メソッドでトータルの秒数を取得することも可能。

print(td.days)
# 447

print(td.seconds)
# 75600

print(td.microseconds)
# 0

print(td.total_seconds())
# 38696400.0

秒を分や時間に変換したい場合は以下の記事を参照。

timedeltaオブジェクトは引き算の順番によって負の値になる場合がある。負のtimedeltaオブジェクトはdaysが負でsecondsmicrosecondsは正になる。

td_m = dt1 - dt2

print(td_m)
# -448 days, 3:00:00

print(td_m.days)
# -448

print(td_m.seconds)
# 10800

print(td_m.total_seconds())
# -38696400.0

timedeltaオブジェクトに対しても組み込み関数abs()が有効。単純に時間差の日数や秒数を取得したい場合はabs()を使うと引き算の順番を考慮しなくてもよいので便利。

td_abs = abs(dt1 - dt2)

print(td_abs)
# 447 days, 21:00:00

print(td_abs.days)
# 447

print(td_abs.seconds)
# 75600

print(td_abs.total_seconds())
# 38696400.0

dateオブジェクトの引き算

dateオブジェクトでも同様。

d1 = datetime.date(year=2017, month=10, day=10)

print(d1)
# 2017-10-10

print(type(d1))
# <class 'datetime.date'>

d2 = datetime.date(year=2019, month=1, day=1)

print(d2)
# 2019-01-01

td = abs(d1 - d2)

print(td)
# 448 days, 0:00:00

print(type(td))
# <class 'datetime.timedelta'>

datetimeオブジェクトとdateオブジェクトの引き算

datetimeオブジェクトとdateオブジェクトの引き算はエラーとなる。

# print(dt2 - d1)
# TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'datetime.date'

どちらかの型に揃える必要がある。

datetimeオブジェクトはdate()メソッドでdateオブジェクトに変換可能。時刻の情報は失われる。

print(dt2.date())
# 2019-01-01

print(type(dt2.date()))
# <class 'datetime.date'>

print(dt2.date() - d1)
# 448 days, 0:00:00

datetime.combine()dateオブジェクトとtimeオブジェクトからdatetimeオブジェクトを生成できる。

timeオブジェクトはコンストラクタで生成可能。コンストラクタの引数を省略すると00:00:00になる。任意の時刻にしたい場合は引数hour, minute, second, microsecondを指定すればよい。

print(datetime.datetime.combine(d1, datetime.time()))
# 2017-10-10 00:00:00

print(type(datetime.datetime.combine(d1, datetime.time())))
# <class 'datetime.datetime'>

print(dt2 - datetime.datetime.combine(d1, datetime.time()))
# 448 days, 12:00:00

現在時刻と特定の日時との時間差

現在時刻のdatetimeオブジェクトやdateオブジェクトはdatetime.now()date.today()で取得できる。

それらを利用すると現在時刻と特定の日時との差分を算出できる。

print(datetime.datetime.now() - dt2)
# 34 days, 9:30:07.362784

print(datetime.date.today() - d2)
# 34 days, 0:00:00

過去の日時とでも未来の日時とでも比較できる。上述のように、絶対値として時間差を取得したい場合はabs()を使う。

時間差を加減した日時を取得

timedeltaオブジェクトはdatetimeオブジェクトやdateオブジェクトと引き算や足し算などの演算が可能。例えば、1週間前や10日後の日付、50分後の時刻などを簡単に計算して取得できる。

任意の時間差はtimedeltaオブジェクトのコンストラクタに日数や時間、秒数などを指定して生成できる。

指定できるのはweeks, days, hours, minutes, seconds, milliseconds(ミリ秒), microseconds(マイクロ秒)。省略すると0となる。日数が固定ではない月と年は指定できない。

td = datetime.timedelta(weeks=1, hours=20)

print(td)
# 7 days, 20:00:00

print(type(td))
# <class 'datetime.timedelta'>

これをdatetimeオブジェクトやdateオブジェクトとの演算に使用する。

print(dt1)
# 2017-10-10 15:00:00

print(dt1 + td)
# 2017-10-18 11:00:00

print(dt1 - td)
# 2017-10-02 19:00:00

dateオブジェクトとの演算の場合、timedeltaオブジェクトの時刻の情報は無視されるので注意。

print(d1)
# 2017-10-10

print(d1 + td)
# 2017-10-17

print(d1 - td)
# 2017-10-03
スポンサーリンク
シェア

関連カテゴリー

関連記事