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

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

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

秒数と分・時間・日数などとの相互変換については

経過時間を測定

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

time.time() --- 時刻データへのアクセスと変換 — Python 3.7.2 ドキュメント

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()で処理を一時停止しています。

time.sleep() --- 時刻データへのアクセスと変換 — Python 3.7.2 ドキュメント

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

単純に処理にかかった時間をログとして残しておきたいというような用途であればtime.time()を利用するのが適当。 測定結果の秒数を分や時間に変換したい場合は

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

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

datetime --- 基本的な日付型および時間型 — Python 3.7.2 ドキュメント

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が負でsecondsとmicrosecondsは正になります。

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を指定すればOKです。

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オブジェクトとの演算の場合、timedelataオブジェクトの時刻の情報は無視されるので気をつけてください。

print(d1)
# 2017-10-10

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

print(d1 - td)
# 2017-10-03
Last Updated: 6/26/2019, 10:34:03 PM