CHAPTER 1 ・ 書き方を一段上げる / Lesson 03

日付と時間を正しく扱う

日付どうしの引き算、月末、営業日、年度。文字の日付を、計算できる日付に変えます。

目安 20分 ・ インストール不要

このレッスンが終わったら

「日付は文字ではなく date 型で持つと、引き算や比較ができる。文字との変換は strptime / strftime」と言える。

STEP 1

こんな場面、ありませんか?

「請求日から入金まで、何日かかったか」「支払期日は、いつか」。経理や総務では、日付の計算が毎日のように出てきます。ところが、日付を "2025/10/9" のような文字のまま持っていると、困ったことが起きます。

文字の日付を並べ替えるとコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

10/10 が 10/9 より先に来て、9/30 が最後になりました。文字は先頭から1文字ずつ比べられるためです(1 は 9 より小さい、という具合です)。引き算で「何日あいているか」を出すこともできません。

そこで、日付は日付専用の型に変えてから計算します。この回では、その変え方と、日数の差・月末・年度・営業日の求め方を学びます。

STEP 2

日付として扱ってみる

Pythonには、標準で datetime という道具があります。まずは日付どうしの引き算をしてみましょう。

日付どうしの引き算・足し算コードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

date.fromisoformat("2025-10-03") が、文字から日付型(date)を作っています。日付型になると、引き算で日数の差が出て、< で前後の比較ができ、timedelta(days=30) を足して30日後も出せます。timedeltaは、「日数や時間の長さ」を表す型です。

もう1つ。日本でよく見る 2025/10/09 のような書き方は、fromisoformat では読めません。そのときは、書き方の見本を添えて読み込みます。

文字から日付へ、日付から文字へコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

strptime は、日付に時刻を加えた datetime 型を返します。そこから .date() で、日付の部分だけを取り出しています。d.year などで年・月・日を個別に取り出せ、strftime で好きな書き方の文字に戻せます。

STEP 3

文字と日付の行き来を読む

日付の扱いは、文字 → 日付型 → 計算 → 文字の流れで考えると整理できます。

  1. 文字の日付2025/10/09
  2. 日付型にするstrptime / fromisoformat
  3. 計算・比較引き算・足し算・並べ替え
  4. 文字にして表示strftime / f文字列
計算は日付型で、表示するときだけ文字に戻す

strptime に渡した「書き方の見本」を、部品に分けてみます。strptime(文字から日付へ)と strftime(日付から文字へ)は、同じ見本の書き方を使います。

datetime.strptime("2025/10/09", "%Y/%m/%d") の部品
"2025/10/09"読み込む文字
%Y4桁の年
/区切りはそのまま
%m2桁の月
/区切りはそのまま
%d2桁の日

日本語にすると

「2025/10/09」という文字を、年(4桁)/月(2桁)/日(2桁) の並びとして読み、日付にしてください。
よく使う見本の記号
%Y4桁の年(2025)
%m2桁の月(01〜12)
%d2桁の日(01〜31)
%H : %M時:分(時刻つきの文字を読むときに使う)
d.weekday()曜日の番号。月曜が0、火曜が1、…、日曜が6

見本と文字が合っていないと、エラーになります。次の STEP で体験しましょう。

STEP 4

変えて、試す

① 曜日・月末・年度。 月末は、calendar.monthrange(年, 月) で調べます。「その月の最初の曜日の番号」と「その月の日数」の2つが返るので、2番目([1])が月末日です。年度は4月始まりとして、1〜3月は前の年の年度にします。

曜日・月末日・年度を求めるコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

2024年は閏年なので、2月は29日まであります。monthrange が正しく答えてくれます。

② 書き方が合わないと、エラー。 取り込んだデータに 2025/10/01 と 2025-10-03 が混ざっていることがあります(messy.csv がそうです)。

わざと間違える:スラッシュの日付を fromisoformat で読むコードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます

ValueError(値が読めない)になります。1行目は読めますが、2行目は読めません。先に / を - に置き換えれば、どちらも読めます。

messy.csv の日付を、そろえて日付型にするサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

③ 営業日を求める。 支払期日が土日や祝日なら、次の営業日にずらす、という決まりがよくあります。holidays.csv(2025年の祝日)を読み、「土日でも祝日でもない日」を営業日とします。祝日の集まりは set(重複のない集まりで、in で「含まれるか」を調べるのが得意)にします。詳しくは Lesson 07 で学びます。

次の営業日を求めるサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

10月10日は金曜なので、そのままです。10月13日はスポーツの日(月曜の祝日)なので、翌日の14日。11月22日は土曜で、23日は日曜(かつ祝日)、24日は振替休日なので、25日(火曜)になります。最後の11月30日は日曜日で、「月末締め翌月末払い」で10月末の分の支払期日が日曜に当たったときの例です。12月1日(月曜)にずれます。

STEP 5

自分で書く

お題① 請求日 2025-09-30 から、入金日 2025-10-28 まで、何日かかったか(日数だけ)を表示してください。

お題①:請求から入金までの日数コードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

(paid - billed).days で、日数が数値で取り出せます。

答えの例を見る
from datetime import date

billed = date.fromisoformat("2025-09-30")
paid = date.fromisoformat("2025-10-28")

print((paid - billed).days)

お題② 2024-02-10 が含まれる月の、月末日(日付)を表示してください。

お題②:月末の日付コードは書き換えられます
Ctrl / ⌘ + Enter でも実行
結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

last = calendar.monthrange(d.year, d.month)[1] で月末の日が出ます。date(d.year, d.month, last) を print します。

答えの例を見る
import calendar
from datetime import date

d = date.fromisoformat("2024-02-10")

last = calendar.monthrange(d.year, d.month)[1]
print(date(d.year, d.month, last))

お題③ 支払期日 2025-11-22 が休みなら、次の営業日にずらして、その日付を表示してください(祝日の読み込みまでは用意してあります)。

お題③:休みなら次の営業日へサンプルファイル付き・書き換えOK
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

while due.weekday() >= 5 or due in holidays: の中で、due = due + timedelta(days=1) とします。ループのあとで due を表示します。

答えの例を見る
import csv
from datetime import date, timedelta

with open("holidays.csv", encoding="utf-8") as f:
  holidays = set([date.fromisoformat(r["日付"]) for r in csv.DictReader(f)])

due = date.fromisoformat("2025-11-22")

while due.weekday() >= 5 or due in holidays:
  due = due + timedelta(days=1)
print(due)
STEP 6

仕事ならどう使う?

理解チェック「2025/10/09」という文字を日付にしたいとき、strptime に渡す書き方の見本は、どれでしょう?

理解チェックdate(2025, 11, 22).weekday() の結果は 5 です。何曜日でしょう?