Python:標準ライブラリ活用(datetime / os / json)
1学習の目的
- datetime で日付の計算と書式変換ができるようになる。納期計算や期限判定を自分で書けるようになる。
- os でパスやフォルダを安全に扱い、json で設定やAPI応答を読み書きできるようになる。実務スクリプトに必要な標準装備がここで揃う。
2基礎解説
| やりたいこと | 書き方 | 結果 |
|---|---|---|
| 日時を作る | datetime(2026, 1, 15) | 2026年1月15日 |
| 日時→文字列 | d.strftime("%Y/%m/%d") | 2026/01/15 |
| 文字列→日時 | datetime.strptime(s, "%Y-%m-%d") | 日時オブジェクト |
| 辞書⇔JSON文字列 | json.dumps / json.loads | 相互に変換 |
- 日時の足し引きは timedelta(days=30)。日時同士を引くと timedelta が返り、.days で日数が取れる。
- strftime は「日時→文字列」、strptime は「文字列→日時」。p は parse(解析)の p と覚えると混同しない。
- 書式記号は %Y年 %m月 %d日 %H時 %M分。月と分はどちらもmだが大文字小文字で別物。
- パスは os.path.join("data", "a.csv") で組み立てる。文字列を + でつなぐとOSごとの区切り文字の違いで壊れる。
- JSONで日本語を出すなら ensure_ascii=False が必須。末尾に s が付くのが文字列用(dumps/loads)、付かないのがファイル用(dump/load)。
現場使用例:ログのタイムスタンプ、締め日・納期の計算、設定ファイル(config.json)の読み書き、APIレスポンスの解析、保存先フォルダの自動作成。
from datetime import datetime, timedelta
import os
import json
d = datetime(2026, 1, 15)
print(d.strftime("%Y年%m月%d日")) # 2026年01月15日
later = d + timedelta(days=30)
print(later.strftime("%Y/%m/%d")) # 2026/02/14
print((later - d).days) # 30
print(os.path.join("data", "sales.csv")) # data/sales.csv
config = {"name": "田中", "age": 30}
text = json.dumps(config, ensure_ascii=False)
print(text) # {"name": "田中", "age": 30}
print(json.loads(text)["name"]) # 田中
3基本ドリル(10問)
出力 == 2026年01月15日
from datetime import datetime してから datetime(2026, 1, 15)。表示は strftime("%Y年%m月%d日")。
from datetime import datetime
d = datetime(2026, 1, 15)
print(d.strftime("%Y年%m月%d日"))
%m や %d は2桁ゼロ埋めで出力される(1月→01)。ゼロを付けたくない場合は自分で int にして f-string で組み立てる。
A. strptime B. strftime C. tostring D. format_date 選択★☆☆無料
解答 == B
f は format(書式化)の f。
B
strftime = string format time(日時→文字列)、strptime = string parse time(文字列→日時)。方向を取り違えるのが最頻出のミス。
出力 == 2026/02/14
timedelta(days=30) を足す。timedelta も datetime からインポートする。
from datetime import datetime, timedelta
d = datetime(2026, 1, 15) + timedelta(days=30)
print(d.strftime("%Y/%m/%d"))
月をまたぐ計算もうるう年もPythonが自動で処理する。日数を自分で31や28と数える必要はない。
import json
config = {"name": "田中"}
print(json.____(config, ensure_ascii=False))
出力 == {"name": "田中"}
「文字列に出力する」ほう。末尾に s が付く。
print(json.dumps(config, ensure_ascii=False))
dumps は dump string の略。ファイルに直接書くときは s の付かない dump を使う。
A. そのまま日本語 B. \u7530\u4e2d のようなエスケープ表記 C. 文字化けする D. エラーになる 選択★☆☆無料
解答 == B
既定では ASCII 文字だけで表現しようとする。
B
データとしては正しく復元できるが人間が読めない。設定ファイルなど目視する用途では必ず ensure_ascii=False を付ける。
出力 == 45
日時同士を引き算し、結果の .days を取り出す。
from datetime import datetime a = datetime(2026, 1, 15) b = datetime(2026, 3, 1) print((b - a).days)
引き算の結果は timedelta。.days を付けないと「45 days, 0:00:00」という表記になるので注意。
from datetime import datetime
d = datetime.____("2026-01-15", "%Y-%m-%d")
print(d.strftime("%Y年%m月%d日"))
出力 == 2026年01月15日
文字列を解析(parse)するほう。第2引数で元の文字列の形を教える。
strptime
第2引数は入力側の書式。CSVやAPIから来る日付は文字列なので、まずこれで日時に変換してから計算する。
A. json.loads B. json.load C. json.read D. json.parse 選択★★☆無料
解答 == B
s が付くほうと付かないほう、どちらがファイル用か。
B
s あり=文字列(string)相手、s なし=ファイル相手。この1文字の違いだけなので、間違えたら思い出したい。
出力 == report.csv / .csv(2行)
os.path.basename() と os.path.splitext()。splitext は (名前, 拡張子) のタプルを返す。
import os path = "data/report.csv" print(os.path.basename(path)) print(os.path.splitext(path)[1])
文字列を split("/") や split(".") で切るより確実で読みやすい。拡張子にドットが含まれる点に注意(".csv")。
出力 == 田中 / 30(2行)
保存は json.dump(config, f, ensure_ascii=False)、読み込みは json.load(f)。どちらも s は付かない。
import json
config = {"name": "田中", "age": 30}
with open("config.json", "w", encoding="utf-8") as f:
json.dump(config, f, ensure_ascii=False)
with open("config.json", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded["name"])
print(loaded["age"])
読み返すと元の型が復元されるのがJSONの利点。CSVだと 30 が "30" になってしまうが、JSONなら数値のまま戻る。
4実践シナリオ(5問)
出力3行が完全一致
注文日に timedelta(days=日数) を足す。f-string の中で strftime を使うときは引用符の種類を変える(外が " なら中は ')。
from datetime import datetime, timedelta
order_date = datetime(2026, 1, 15)
items = [("ノートPC", 7), ("マウス", 3), ("特注品", 30)]
for name, days in items:
due = order_date + timedelta(days=days)
print(f"{name}:{due.strftime('%Y/%m/%d')}({days}日後)")
月をまたぐ「特注品」も自動で2月14日になる。締め日・納期・有効期限の計算はすべてこの形で書ける。
出力3行が完全一致
strptime で日時に変換してから strftime で書式化する。曜日は d.weekday() が0(月曜)〜6(日曜)を返すので WEEK の添字に使える。
from datetime import datetime
WEEK = ["月", "火", "水", "木", "金", "土", "日"]
raw = ["2026-01-05", "2026-02-14", "2026-03-01"]
for r in raw:
d = datetime.strptime(r, "%Y-%m-%d")
print(f"{d.strftime('%Y年%m月%d日')}({WEEK[d.weekday()]})")
文字列 → 日時 → 別の文字列という変換は日常茶飯事。曜日名は環境によって英語になることがあるため、自前のリストで持つほうが確実。
「初期設定:{...}」「変更後:{...}」「テーマ:dark」の3行。 コーディング★★☆無料
出力3行が完全一致
読み込んだ辞書はそのまま書き換えられる。保存 → 読み込み → 変更 → 保存 → 読み込みの順で処理する。
import json
settings = {"theme": "light", "font_size": 14}
with open("settings.json", "w", encoding="utf-8") as f:
json.dump(settings, f, ensure_ascii=False)
with open("settings.json", encoding="utf-8") as f:
loaded = json.load(f)
print(f"初期設定:{loaded}")
loaded["theme"] = "dark"
loaded["font_size"] = 16
with open("settings.json", "w", encoding="utf-8") as f:
json.dump(loaded, f, ensure_ascii=False)
with open("settings.json", encoding="utf-8") as f:
final = json.load(f)
print(f"変更後:{final}")
print(f"テーマ:{final['theme']}")
アプリの設定保存はほぼこの形。PY12ではconfig.pyに書いたが、JSONならプログラムから安全に書き換えられる点が違う。
出力4行が完全一致
拡張子は os.path.splitext(name)[1] で取れるが先頭にドットが付くので .lstrip(".") で外す。件数は辞書で数え、フォルダ作成は os.makedirs(ext, exist_ok=True)。
import os
files = ["report.csv", "photo.png", "data.csv", "memo.txt", "chart.png"]
groups = {}
for name in files:
ext = os.path.splitext(name)[1].lstrip(".")
groups[ext] = groups.get(ext, 0) + 1
os.makedirs(ext, exist_ok=True)
for ext, count in groups.items():
print(f"{ext}/ ← {count}件")
print(f"作成したフォルダ:{sorted(groups.keys())}")
exist_ok=True を付けると既にフォルダがあってもエラーにならない。ダウンロードフォルダの自動整理など、実生活で今日から使えるスクリプトの原型。
response = '{"status": 200, "data": {"users": [{"name": "田中", "age": 30}, {"name": "鈴木", "age": 25}]}}'
「ステータス:200」「ユーザー数:2人」「田中(30歳)」「鈴木(25歳)」「平均年齢:27.5歳」の5行を出力すること。 コーディング★★★無料
出力5行が完全一致
json.loads で辞書にすると result["data"]["users"] のように階層をたどって取り出せる。年齢だけのリストは内包表記で作る。
import json
response = '{"status": 200, "data": {"users": [{"name": "田中", "age": 30}, {"name": "鈴木", "age": 25}]}}'
result = json.loads(response)
users = result["data"]["users"]
print(f"ステータス:{result['status']}")
print(f"ユーザー数:{len(users)}人")
for u in users:
print(f"{u['name']}({u['age']}歳)")
ages = [u["age"] for u in users]
print(f"平均年齢:{sum(ages) / len(ages)}歳")
APIの応答はほぼこの形(辞書の中にリスト、リストの中に辞書)。階層が深くても、辞書とリストの組み合わせでしかないと分かれば怖くない。PY16でこれを本物のAPIから取得する。
5仕上げ課題
BASE_DATE = datetime(2026, 1, 15) # 実行日として固定
LIMIT_DAYS = 7
files = [
("sales.csv", 120, "2026-01-14"),
("old_report.pdf", 2400, "2025-12-01"),
("memo.txt", 3, "2026-01-15"),
("archive.zip", 51200, "2026-01-09"),
] # (ファイル名, サイズKB, 更新日)
仕様:
① 更新日が LIMIT_DAYS 以内なら「[対象]」、超えていれば「[除外]」で表示
② 対象のファイル名と合計サイズを集計
③ "backup" フォルダを作成し、report_20260115.json という名前でレポートを保存
(保存する辞書:date / count / total_kb / files)
④ 保存したJSONを読み返し、キーと値を1行ずつ表示
出力仕様(14行):
=== バックアップレポート 2026年01月15日 ===
[対象] sales.csv(120KB / 1日前)
[除外] old_report.pdf(45日前)
[対象] memo.txt(3KB / 0日前)
[対象] archive.zip(51,200KB / 6日前)
---
対象:3件 / 合計51,323KB
backup フォルダに report_20260115.json を保存しました
---
[JSONを読み返し]
date: 2026-01-15
count: 3
total_kb: 51323
files: ['sales.csv', 'memo.txt', 'archive.zip']
出力14行が完全一致
更新日は文字列なので strptime で日時に変換してから (BASE_DATE - d).days で経過日数を求める。ファイル名は f"report_{BASE_DATE.strftime('%Y%m%d')}.json" で作り、保存先は os.path.join("backup", filename)。読み返しは for key, value in loaded.items(): で回す。
import json
import os
from datetime import datetime
BASE_DATE = datetime(2026, 1, 15)
LIMIT_DAYS = 7
files = [
("sales.csv", 120, "2026-01-14"),
("old_report.pdf", 2400, "2025-12-01"),
("memo.txt", 3, "2026-01-15"),
("archive.zip", 51200, "2026-01-09"),
]
print(f"=== バックアップレポート {BASE_DATE.strftime('%Y年%m月%d日')} ===")
targets = []
total_kb = 0
for name, size, updated in files:
d = datetime.strptime(updated, "%Y-%m-%d")
days = (BASE_DATE - d).days
if days <= LIMIT_DAYS:
targets.append(name)
total_kb += size
print(f"[対象] {name}({size:,}KB / {days}日前)")
else:
print(f"[除外] {name}({days}日前)")
os.makedirs("backup", exist_ok=True)
report = {
"date": BASE_DATE.strftime("%Y-%m-%d"),
"count": len(targets),
"total_kb": total_kb,
"files": targets,
}
filename = f"report_{BASE_DATE.strftime('%Y%m%d')}.json"
path = os.path.join("backup", filename)
with open(path, "w", encoding="utf-8") as f:
json.dump(report, f, ensure_ascii=False)
print("---")
print(f"対象:{len(targets)}件 / 合計{total_kb:,}KB")
print(f"backup フォルダに {filename} を保存しました")
print("---")
print("[JSONを読み返し]")
with open(path, encoding="utf-8") as f:
loaded = json.load(f)
for key, value in loaded.items():
print(f"{key}: {value}")
日付で判定し、フォルダを作り、結果をJSONで残す——実務の定期実行スクリプトが備えるべき要素が全部入っている。ファイル名に日付を埋め込むのは実行日ごとに履歴を残す定番の手法で、後から「いつのレポートか」が一目で分かる。BASE_DATE を datetime.now() に差し替えれば、そのまま毎日動く本物のバックアップスクリプトになる。