skip to content
barorin&

Pythonの日付処理まとめ|文字列変換・月末計算・前年同期比

/ 9 min read

Table of Contents

はじめに

会計や経理の仕事は、ほぼすべてが日付に紐づいています。月末、四半期末、決算日、前年同期。データを触るときも「当月末を求める」「前年の同じ月と比べる」といった処理が延々と出てきます。

この記事では、Python単体の datetime とpandasの両方で、日付処理の実務パターンをまとめました。特に月末の計算は間違えやすく、しかも間違えても普段は気づきにくいので、そこは重点的に書いています。

現在日時を取得して書式を整える

00.123456
import datetime
dt_now = datetime.datetime.now()
dt_now.strftime("%Y年%m月%d日 %H:%M:%S")
# 2026年08月30日 10:00:00

strftime() の書式は覚える必要はなく、よく使うのはこのあたりです。

書式 意味 出力例
%Y 西暦4桁 2026
%m 月(ゼロ埋め) 08
%d 日(ゼロ埋め) 30
%b 月の英語略称 Aug
%H:%M:%S 時分秒 10:00:00

文字列を日付型に変える

会計システムやCSVから出てきた日付は、たいてい文字列です。strptime() で書式を教えて変換します。

import datetime
t = "May 26, 2022"
t2 = datetime.datetime.strptime(t, "%b %d, %Y")
# datetime.datetime(2022, 5, 26, 0, 0)
# 時刻が不要なら date 型にする
t3 = t2.date()
# datetime.date(2022, 5, 26)

pandasなら列まるごと一発です。

import pandas as pd
df["date"] = pd.to_datetime(df["date"], format="%b %d, %Y")

変換できない値が混ざっているとき

実務のデータには や空欄が平気で混ざります。errors="coerce" を付けると、変換できない値を NaT(日付版のNaN)にして処理を止めずに進められます。

df["date"] = pd.to_datetime(df["date"], errors="coerce")
# 変換できなかった行を確認する
df[df["date"].isna()]

日付の加算・減算

日数の加算なら標準の timedelta で足りますが、月単位の加算には relativedelta が必要です。「1ヶ月後」は月によって28〜31日と長さが変わるためです。

Terminal window
$ pip install python-dateutil
from datetime import datetime
from dateutil.relativedelta import relativedelta
today = datetime.today()
# 年月日をそれぞれ取り出す
year, month, day = today.year, today.month, today.day
# n日の加算・減算
today + relativedelta(days=3) # 3日後
today + relativedelta(days=-3) # 3日前
# n月の加算・減算
today + relativedelta(months=3) # 3ヶ月後
today + relativedelta(months=-3) # 3ヶ月前
# 1年前の同じ日(前年同期の比較で使う)
today + relativedelta(years=-1)

月末を正しく求める

ここが本題です。「当月末」を求めるつもりで、次のように書くのは間違いです。

# NG: これは「1ヶ月後の前日」であって当月末ではない
today + relativedelta(months=1, days=-1)

2026年8月30日に実行すると 2026-09-29 が返ります。もっと分かりやすいのは2月で、2026年2月10日に実行すると 2026-03-09 になります。月末どころか翌月です。

正しくは、relativedeltaday(単数形) を使います。単数形の day は「その月の指定日にセットする。月の日数を超える場合は月末にクリップする」という挙動なので、day=31 と書けば常に当月末になります。

# OK: 常に当月末が返る
today + relativedelta(day=31)
実行日 months=1, days=-1(誤) day=31(正)
2026-08-30 2026-09-29 2026-08-31
2026-02-10 2026-03-09 2026-02-28
2024-02-10 2024-03-09 2024-02-29

うるう年も自動で処理されます。標準ライブラリだけで済ませたい場合は calendar を使います。

import calendar
from datetime import date
y, m = 2026, 2
last_day = calendar.monthrange(y, m)[1] # -> 28
date(y, m, last_day) # -> 2026-02-28

前月末・翌月末・期末日

月末の求め方さえ分かれば、応用は簡単です。

# 前月末
today + relativedelta(months=-1, day=31)
# 翌月末
today + relativedelta(months=1, day=31)
# 3月決算の期末日(当年の3月31日)
today.replace(month=3) + relativedelta(day=31)

pandasの列に対しては offsets を使うと素直に書けます。

import pandas as pd
# 各行の日付を、その月の月末に丸める
df["月末"] = df["date"] + pd.offsets.MonthEnd(0)
# 四半期末に丸める
df["四半期末"] = df["date"] + pd.offsets.QuarterEnd(0)

MonthEnd(0)0 は「すでに月末ならそのまま」という意味です。1 にすると月末の日でも翌月末に飛ぶので、集計キーを作る用途では 0 を使います。

日付列の表示を YYYY/MM/DD に揃える

pd.to_datetime() した列をそのまま出力すると時分秒まで付いてきます。表示用に整えるには .dt.strftime() を使います。

df["date"] = pd.to_datetime(df["date"]).dt.strftime("%Y/%m/%d")

前年同期比を計算する

月次の時系列データに前年比の列を足します。

date value
2025-01-01 10
2025-02-01 20
2026-01-01 15
2026-02-01 40

pct_change()periods に12を指定すると、12行前(=前年同月)との変化率が出ます。

df["前年比"] = df["value"].pct_change(periods=12)
# 最初の12ヶ月分はNaNになるのでゼロ埋め
df["前年比"] = df["前年比"].fillna(0)
date value 前年比
2025-01-01 10 0
2025-02-01 20 0
2026-01-01 15 0.5
2026-02-01 40 1.0

月が欠けている可能性があるデータなら、日付をインデックスにして asfreq() で月次に揃えてから計算すると確実です。

df = df.set_index("date").asfreq("MS") # MS = 月初基準
df["前年比"] = df["value"].pct_change(periods=12).fillna(0)

おわりに

日付処理は、間違えても例外が出ず、それらしい値が返ってくるのが厄介なところです。特に月末の計算は、月中に動かしているうちは誰も気づきません。決算や月次の締めに関わる処理を書いたときは、2月・うるう年・月末日の3パターンを通しておくと安心です。

この記事を書いた人

barorinのプロフィール画像

barorin公認会計士

会計とITの二足のわらじで働く公認会計士です。Pythonを中心に、会計・監査の実務で実際に使っているコードや、Ubuntu・Raspberry Piの設定メモを書いています。