CHAPTER 1 ・ 書き方を一段上げる / Lesson 03
日付と時間を正しく扱う
日付どうしの引き算、月末、営業日、年度。文字の日付を、計算できる日付に変えます。
このレッスンが終わったら
「日付は文字ではなく date 型で持つと、引き算や比較ができる。文字との変換は strptime / strftime」と言える。
こんな場面、ありませんか?
「請求日から入金まで、何日かかったか」「支払期日は、いつか」。経理や総務では、日付の計算が毎日のように出てきます。ところが、日付を "2025/10/9" のような文字のまま持っていると、困ったことが起きます。
▶ 実行を押すと、ここに結果が出ます
10/10 が 10/9 より先に来て、9/30 が最後になりました。文字は先頭から1文字ずつ比べられるためです(1 は 9 より小さい、という具合です)。引き算で「何日あいているか」を出すこともできません。
そこで、日付は日付専用の型に変えてから計算します。この回では、その変え方と、日数の差・月末・年度・営業日の求め方を学びます。
日付として扱ってみる
Pythonには、標準で datetime という道具があります。まずは日付どうしの引き算をしてみましょう。
▶ 実行を押すと、ここに結果が出ます
date.fromisoformat("2025-10-03") が、文字から日付型(date)を作っています。日付型になると、引き算で日数の差が出て、< で前後の比較ができ、timedelta(days=30) を足して30日後も出せます。timedeltaは、「日数や時間の長さ」を表す型です。
もう1つ。日本でよく見る 2025/10/09 のような書き方は、fromisoformat では読めません。そのときは、書き方の見本を添えて読み込みます。
▶ 実行を押すと、ここに結果が出ます
strptime は、日付に時刻を加えた datetime 型を返します。そこから .date() で、日付の部分だけを取り出しています。d.year などで年・月・日を個別に取り出せ、strftime で好きな書き方の文字に戻せます。
文字と日付の行き来を読む
日付の扱いは、文字 → 日付型 → 計算 → 文字の流れで考えると整理できます。
- 文字の日付2025/10/09
- 日付型にするstrptime / fromisoformat
- 計算・比較引き算・足し算・並べ替え
- 文字にして表示strftime / f文字列
strptime に渡した「書き方の見本」を、部品に分けてみます。strptime(文字から日付へ)と strftime(日付から文字へ)は、同じ見本の書き方を使います。
"2025/10/09"読み込む文字%Y4桁の年/区切りはそのまま%m2桁の月/区切りはそのまま%d2桁の日日本語にすると
%Y4桁の年(2025)%m2桁の月(01〜12)%d2桁の日(01〜31)%H : %M時:分(時刻つきの文字を読むときに使う)d.weekday()曜日の番号。月曜が0、火曜が1、…、日曜が6見本と文字が合っていないと、エラーになります。次の STEP で体験しましょう。
変えて、試す
① 曜日・月末・年度。 月末は、calendar.monthrange(年, 月) で調べます。「その月の最初の曜日の番号」と「その月の日数」の2つが返るので、2番目([1])が月末日です。年度は4月始まりとして、1〜3月は前の年の年度にします。
▶ 実行を押すと、ここに結果が出ます
2024年は閏年なので、2月は29日まであります。monthrange が正しく答えてくれます。
② 書き方が合わないと、エラー。 取り込んだデータに 2025/10/01 と 2025-10-03 が混ざっていることがあります(messy.csv がそうです)。
▶ 実行を押すと、ここに結果が出ます
ValueError(値が読めない)になります。1行目は読めますが、2行目は読めません。先に / を - に置き換えれば、どちらも読めます。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
③ 営業日を求める。 支払期日が土日や祝日なら、次の営業日にずらす、という決まりがよくあります。holidays.csv(2025年の祝日)を読み、「土日でも祝日でもない日」を営業日とします。祝日の集まりは set(重複のない集まりで、in で「含まれるか」を調べるのが得意)にします。詳しくは Lesson 07 で学びます。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
10月10日は金曜なので、そのままです。10月13日はスポーツの日(月曜の祝日)なので、翌日の14日。11月22日は土曜で、23日は日曜(かつ祝日)、24日は振替休日なので、25日(火曜)になります。最後の11月30日は日曜日で、「月末締め翌月末払い」で10月末の分の支払期日が日曜に当たったときの例です。12月1日(月曜)にずれます。
自分で書く
お題① 請求日 2025-09-30 から、入金日 2025-10-28 まで、何日かかったか(日数だけ)を表示してください。
▶ 実行を押すと、ここに結果が出ます
ヒントを見る
(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 が含まれる月の、月末日(日付)を表示してください。
▶ 実行を押すと、ここに結果が出ます
ヒントを見る
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 が休みなら、次の営業日にずらして、その日付を表示してください(祝日の読み込みまでは用意してあります)。
この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。
▶ 実行を押すと、ここに結果が出ます
ヒントを見る
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)仕事ならどう使う?
理解チェック「2025/10/09」という文字を日付にしたいとき、strptime に渡す書き方の見本は、どれでしょう?
理解チェックdate(2025, 11, 22).weekday() の結果は 5 です。何曜日でしょう?