Python入門|わかりやすい日付計算の基本(足し算,引き算,差分,etc)のイメージ画像

Python入門|わかりやすい日付計算の基本(足し算,引き算,差分,etc)

  • 公開日:2018/05/08
  • 更新日:2018/10/19
  • 投稿者:n bit

Pythonで日付の計算を行うシーンはよくあります。例えば30日サイクルの会員管理等起点日からの時間経過で判別して次のアクションにつなげるようなケース。数値の演算であれば簡単ですが日付の計算ってどうやってやるの?Pythonには日付の演算も簡単に行うためのオブジェクトが用意されています。今回はPythonの日付計算、特によく利用する「加算、減算、差分」について解説します。

  • Python

この記事は約 分で読めます。(文字)

Pythonで日付の足し算と引き算

Pythonでの日付の足し算や引き算は非常に簡単です。ある指定の時間から数時間後や数時間前といった時間を求めたい時はtimedelta オブジェクトを利用します。

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

timedelta オブジェクトに指定できる引数

利用できる引数は7種類で、引数には整数だけでなく浮動小数点、負の数なども使用できます。

引数単位
microsecondsマイクロ秒
millisecondsミリ秒
seconds
minutes
hours
days
weeks

timedelta オブジェクトで日付の加算

では、実際にtimedelta オブジェクトを利用して日付に加算してみましょう。datetimeオブジェクトにtimedelta オブジェクトで引数をしてプラスするだけで計算できます。

from datetime import datetime as dt

from datetime import timedelta

# 現在の時間を取得して変数「now」に格納
now = dt.now()
print('Now Time:' +str(now)) # Now Time:2018-05-07 06:12:01.008714

# 変数「now」に 100マイクロ秒 加算
d = now + timedelta(microseconds=30)
print(d) # 2018-05-07 06:12:01.008814

# 変数「now」に 50ミリ秒 加算
d = now + timedelta(milliseconds=30)
print(d) # 2018-05-07 06:12:01.058714

# 変数「now」に 30秒 加算
d = now + timedelta(seconds=30)
print(d) # 2018-05-07 06:12:31.008714

# 変数「now」に 15分 加算
d = now + timedelta(minutes=15)
print(d) # 2018-05-07 06:27:01.008714

# 変数「now」に 10時間 加算
d = now + timedelta(hours=10)
print(d) # 2018-05-07 16:12:01.008714

# 変数「now」に 5日 加算
d = now + timedelta(days=5)
print(d) # 2018-05-12 06:12:01.008714

# 変数「now」に 3週 加算
d = now + timedelta(weeks=3)
print(d) # 2018-05-28 06:12:01.008714

出力された値から現在時刻にtimedeltaで指定した時間分が加算されているのが分かります。

引数には同時に複数の値を指定可能で、もう少し複雑な時間を加算することができます。

# 5日と10時間15分 加算

d = now + timedelta(days=5, hours=10, minutes=15)
print(d) # 2018-05-12 16:27:01.008714

datetimeオブジェクトか確認

timedeltaを使った日付の計算は、datetimeオブジェクトでないと対応していません。もし上記の加算がうまく行えなかった場合はオブジェクトのタイプがdatetimeになっているかを確認してみてください。

now = dt.now()

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

timedelta オブジェクトで日付の減算

日付の減算も基本的には加算の場合と同じやり方です。プラス記号をマイナス記号に変えるだけで減算できます。

# 変数「now」から 10時間 減算

d = now - timedelta(hours=10)
print(d) # 2018-05-06 20:12:01.008714

# 変数「now」から 5日 減算
d = now - timedelta(days=5)
print(d) # 2018-05-02 06:12:01.008714

# 変数「now」から 3週 減算
d = now - timedelta(weeks=3)
print(d) # 2018-04-16 06:12:01.008714

timedelta オブジェクトは引数に負の数を指定することもできますのでプラスマイナス記号変更せずに引数の値をマイナスに変えるだけでも同じ結果が出力されます。

# 変数「now」から 10時間 減算

d = now + timedelta(hours=-10)
print(d) # 2018-05-06 20:12:01.008714

# 変数「now」から 5日 減算
d = now + timedelta(days=-5)
print(d) # 2018-05-02 06:12:01.008714

# 変数「now」から 3週 減算
d = now + timedelta(weeks=-3)
print(d) # 2018-04-16 06:12:01.008714

Pythonで2つの日付間の差分を求める

ここまでは日付に対する加算や減算を求めてきましたが、次は2つの日付間や時刻間の差分を求めていきます。日付間や時刻間の差分の求め方はそのまま日付から日付を引き算すれば求めることができます。

from datetime import datetime as dt

from datetime import timedelta


# 現在の時間を取得して変数「now」に格納

now = dt.now()

print('Now Time:' +str(now)) # Now Time:2018-05-07 06:12:01.008714


# 変数「now」に 5日 加算

d = now + timedelta(days=5)

print(d) # 2018-05-12 06:12:01.008714


# 日付間の差分を求める
print(d-now) # 5 days, 0:00:00

現在時刻にtimedeltaで5日追加したものから現在時刻を引いた場合、差分は5日と表示されています。もともと現在時刻に5日足していますので当たり前ですが、このように直接datetime同士を引き算することでとても簡単に差分を求めることができます。

最終出力された値は通常のdatetimeオブジェクトと違う表記形式になっていますがこれは何でしょうか。実はこれはtimedelta オブジェクトです。ここでtimedelta オブジェクトについて少し理解しておきましょう。

timedelta オブジェクトとは

先ほどまで何気なくtimedelta オブジェクトを利用してきましたが、実はtimedelta オブジェクトとは2つの日付や時刻間の差分を表すオブジェクトです。つまり、経過時間を表しています。

Note

timedelta オブジェクトとは

2つの日付や時刻間の差分を表すオブジェクト

出典:8.1. datetime — 基本的な日付型および時間型 — Python 3.6.5 ドキュメント

加算や減算では、現在時刻からプラスの経過時間やマイナスの経過時間を足し引きして求めていたと言うことです。

timedelta オブジェクトは、「2つの日付間の経過時間」ですので、2つの日付を引き算をして差分(つまり、2つの日付間の経過時間)を求めると出力される値は自動的にtimedelta オブジェクトになります。

  • \(datetime - datetime = timedelta(2つの日付間の経過時間)\)

timedelta オブジェクトの出力値

出力されるtimedelta オブジェクトの出力値を個別に取得することができます。通常timedelta オブジェクトをそのまま出力すると経過時間が出力されます。

# 5日と10時間15分100マイクロ秒 加算

d = now + timedelta(days=5, hours=10, minutes=15, microseconds=100)
print(d-now) # 5 days, 10:15:00.000100

これに属性を追加することで出力値を個別に取得することができます。

# 5日と10時間15分100マイクロ秒 加算

d = now + timedelta(days=5, hours=10, minutes=15, microseconds=100)
print(d-now) # 5 days, 10:15:00.000100

# 差分日数のみを取得
print((d-now).days) # 5

# 差分秒数のみを取得
print((d-now).seconds) # 36900

# 差分マイクロ秒数のみを取得
print((d-now).microseconds) # 100

属性で使用することができるのは3種類です。何日経過したかだけを知りたい場合はdays、何秒経過したかだけを知りたい場合はseconds、何マイクロ秒経過したかだけを知りたい場合はmicrosecondsを利用します。

属性単位
days差分日数
seconds差分秒数
microseconds差分マイクロ秒数

それぞれの値には属性には出力できる範囲があります。汎用超えている差分に関しては出力値に含まれません。

属性単位
days-999999999 から 999999999 日の間
seconds 0 から 86399 秒の間(23時間59分59秒迄)
microseconds0 から 999999 マイクロ秒の間

例えば、

# 差分秒数のみを取得

print((d-now).seconds) # 36900

secondsは、36900秒という出力値を返していますが、これは時分に直すと10時間15分になります。つまり、secondsには秒以下の単位や、1日以上の単位に関しては含まれていないと言うことです。秒以下の単位に関してはmicrosecondsで出力し、1日以上の単位に関してはdaysで出力されます。

Pythonで日付計算の応用

timedelta オブジェクトはその他にも様々な機能が用意されています。その中でも割と使うものを応用編として掲載しておきます。

経過日数を変数で指定する

timedelta オブジェクトは、timedelta単体、または、timedelta同士のかけ算、割り算、剰余にも対応しています。これにより様々なケースで活用することができます。

# 経過日数を変数「add_day」に格納

add_day = 2.5


# 変数「now」に 2.5日 加算
d = now + (timedelta(days=1) * add_day)

# 日付間の差分を求める
print(d-now) # 2 days, 12:00:00

経過日数を全て秒数で出力する

差分を全て秒数で出力させたい場合はtotal_seconds()が便利です。timedeltaの属性secondsとは違い差分全てを秒数に変更して出力します。

# 経過日数を変数「add_day」に格納

add_day = 2.5


# 変数「now」に 2.5日 加算
d = now + (timedelta(days=1) * add_day)

# 日付間の差分を求める
print((d-now).total_seconds()) # 216000.0

今日のdot

Pythonで日付の計算で、「加算、減算、差分」を求める場合にはtimedelta オブジェクトを利用します。timedelta オブジェクトとは「2つの日付や時刻間の差分を表すオブジェクト」で、経過時間を表しています。timedeltaを使ったdatetimeの計算でサポートされているのは下記の3つです。

  • \(datetime + timedelta = datetime(日付に経過時間の加算)\)
  • \(datetime - timedelta = datetime(日付に経過時間の減算)\)
  • \(datetime - datetime = timedelta(2つの日付間の経過時間)\)

datetimeにtimedeltaを足し引きした場合出力される値はdatetimeですが、datetime同士で引き算した場合は出力される値がtimedeltaにかわります。