日付と日付時刻の変更

日付と日付時刻の変更方法の紹介をします。

日付と日付時刻はdatetimeモジュールのdateとdatetimeを使います。

timedeltaによる変更

日付と日付時刻のデータに対し、datetimeモジュールのtimedeltaを足したり引いたりできます。これにより時刻を進めたり戻したりできます。

下記は、2021年10月1日を表す日付時刻の変数dtに対し、10日と5秒後を求めて表示する例です。

from datetime import datetime, timedelta

print(datetime(2021, 10, 1) + timedelta(10, 5))  # 2021-10-11 00:00:05

timedeltaのデータは、timedelta(日数, 秒数)のように作成します。他にも、時間数、分数、週数なども指定できます。 また、timedeltaのデータは、日付時刻のデータだけでなく日付データに対しても使えます。

参考:datetime --- 基本的な日付型および時間型

timedeltaを使うと、日付と日付時刻の「X日後」「X日前」を計算できます。 しかし、「Xヶ月後」「X年後」を計算することはできません。この場合は次節のようにrelativedeltaを使います。

relativedeltaによる変更

relativedeltaのデータは、timedeltaと同じように日付や日付時刻に足したり引いたりできます。 relativedeltaは、dateutil.relativedeltaモジュールで定義されています。

なお、dateutilは標準モジュールではないため、下記のようにpython-dateutilモジュールをインストールして使います。

pip install python-dateutil

relativedeltaを使うと、「Xヶ月後」「X年後」を計算できます。それだけではなく、作成時に指定できる項目は多岐に渡ります。

relativedeltaデータの作成方法

relativedeltaは、絶対値と相対値とその他の3種類の値を設定できます。 設定可能な値は、以下の表の通りですが、設定しない場合は無視されます(表は引数の順番になっています)。

種類

仮引数

意味

その他

dt1

日付時刻1

その他

dt2

日付時刻2

相対値

years

年

相対値

months

月

相対値

days

日

相対値

leapdays

-1の場合、うるう日を無視する

相対値

weeks

週

相対値

hours

時

相対値

minutes

分

相対値

seconds

秒

相対値

microseconds

マイクロ秒

絶対値

year

年

絶対値

month

月

絶対値

day

日

その他

weekday

N週の曜日

絶対値

yearday

前年大晦日からの日数

絶対値

nlyearday

前年大晦日からのうるう日を無視した日数

絶対値

hour

時

絶対値

minute

分

絶対値

second

秒

絶対値

microsecond

マイクロ秒

dt1, dt2の両方が指定されると、dt1 - dt2の相対値となります。また、そのときはその他の指定は無視されます。

leapdaysは、yearday指定時に内部で使われており、使用はおすすめしません。

weekday以外の相対値は整数です。絶対値はNoneまたは整数です。 weekdayは、曜日を意味するMO, TU, WE, TH, FR, SA, SUのいずれかです。

MOとMO(1)は同じ意味です。また、すでに月曜であればMOとMO(-1)は同じ結果です。 MO(2)とすると2回目の月曜日という意味になります。 MO(-2)とすると2回前の月曜日という意味になります。 MO(0)は使いません。

演算ルール

ここでは、relativedeltaのシンプルな使い方を紹介します。詳細はdateutil.relativedelta を参照ください。

  • 対象値 + 更新値または対象値 - 更新値で対象値を更新します。対象値は日付または日付時刻です。更新値はrelativedeltaのデータです(後述の実行例その1参照)。

  • 最初に、対象値に「更新値の絶対値」を上記の表の上から順番に設定します(後述の実行例その2参照)。

  • 次に、対象値に「更新値の相対値」を上記の表の上から順番に加算または減算します。

  • 最後に、更新値にweekdayがあればその曜日になるように加算または減算します。すでにその曜日であれば、変化しません(後述の実行例その3参照)。

  • relativedeltaに数値をかけると、相対値をその倍数にします。そのとき、小数点以下は切り捨てられて整数になります(後述の実行例その1参照)。

演算

  • dateにrelativedeltaを足したり引いたりしたものは、dateです。ただし、0時0分以外になった場合は、datetimeになります。

  • datetimeにrelativedeltaを足したり引いたりしたものは、datetimeです。

  • 「relativedelta * 数字」は、relativedeltaです。

  • 「relativedelta + relativedelta」や「relativedelta - relativedelta」は、relativedeltaです。

参考:dateutil.relativedelta

実行例その1

from datetime import date
from dateutil.relativedelta import relativedelta

dt = date(2020, 1, 31)  # dateのデータ
rd = relativedelta(months=1)  # relativedeltaのデータ

print(dt - rd)  # 2019-12-31
print(dt + rd)  # 2020-02-29
print(dt + rd * 3)  # 2020-04-30
  • 2020-01-31の日付を表す変数dtを作成します。

  • rd = relativedelta(months=1)は、「1ヶ月」を意味します(monthsは相対値です)。

  • dt - rdは1ヶ月前なので、2019-12-31です。

  • dt + rdは1ヶ月後です。2020-02-31は存在しないので2月の最終日の2020-02-29になります。

  • rd * 3は「3ヶ月」になります。したがって、dt + rd * 3は、3ヶ月後の2020-04-30です。

実行例その2

dt = date(2020, 1, 31)  # dateのデータ

rd1 = relativedelta(day=3)
print(dt + rd1)  # 2020-01-03

rd2 = relativedelta(day=3, yearday=7)
print(dt + rd2)  # 2020-01-07
  • 2020-01-31の日付を表す変数dtを作成します。

  • dt + rd1は、rd1の絶対値である引数day=3の指定により、2020-01-03になります。

  • dt + rd2は、rd2の引数の中から、表の上にある方のday=3の指定により、一旦、2020-01-03になります。その後、yearday=7の指定により、2020-01-07になります。つまり、yeardayの方が優先されます。

実行例その3

from dateutil.relativedelta import FR, SA

dt = date(2020, 1, 31)  # dateのデータ

rd1 = relativedelta(weekday=SA)
print(dt + rd1)  # 2020-02-01

rd2 = relativedelta(weekday=FR)
print(dt + rd2)  # 2020-01-31
  • 2020-01-31の日付を表す変数dtを作成します。

  • dt + rd1は、rd1の引数weekday=SAの指定により、次の土曜日の2020-02-01になります。

  • dt + rd2は、rd2の引数weekday=FRの指定がありますが、2020-01-31が金曜日なので、変わらずに2020-01-31になります。