Pythonでは、日付や時刻を文字列にしたり、文字列から日付に戻したりする操作は標準ライブラリだけで十分に扱えます。
この記事では日付の書式を指定して文字列とdatetimeを相互変換する基本を、初心者でもそのままコピペして使えるサンプルとともに詳しく解説します。
最短距離で使いながら覚えたい方に向けた実用記事です。
Pythonのdatetimeで日付文字列を相互変換する基本
strftime/strptimeの役割
strftime
はdatetimeを文字列へ、strptime
は文字列をdatetimeへ変換します。
どちらもdatetime
型のメソッドや関数として提供され、フォーマット指定子(例:%Y
や%m
)を並べた書式文字列で形を整えます。
タイムゾーンを扱わない素の日時(naive datetime)を前提に解説します。
datetime → 文字列(基本)
datetimeから好きな形の文字列に変換するにはstrftime
を使います。
固定日時を使うことで出力が再現できます。
from datetime import datetime
# 固定の日時(2025-09-16 13:05:09.123456)を用意
dt = datetime(2025, 9, 16, 13, 5, 9, 123456)
# datetime → 文字列: よくある3パターン
s1 = dt.strftime("%Y-%m-%d") # 2025-09-16
s2 = dt.strftime("%Y/%m/%d %H:%M:%S") # 2025/09/16 13:05:09
s3 = dt.strftime("%Y-%m-%dT%H:%M:%S") # 2025-09-16T13:05:09 (ISO 8601風)
print(s1)
print(s2)
print(s3)
2025-09-16
2025/09/16 13:05:09
2025-09-16T13:05:09
文字や記号(例:「年」「/」「T」)はそのまま書けば固定文字として出力されます。
文字列 → datetime(基本)
文字列からdatetimeへはdatetime.strptime
を使います。
文字列の形と完全に一致するフォーマットを指定するのがコツです。
from datetime import datetime
s = "2025-09-16 13:05:09"
dt = datetime.strptime(s, "%Y-%m-%d %H:%M:%S") # 文字列 → datetime
print(dt, type(dt)) # できあがりを確認
print(dt.strftime("%Y/%m/%d")) # 好きな形に再出力
2025-09-16 13:05:09 <class 'datetime.datetime'>
2025/09/16
まずstrptime
でdatetimeへ変換し、その後strftime
で任意の形に整えるのが「書式変換」の基本レシピです。
よく使う日付フォーマット指定子一覧(strftime/strptime)
ここに挙げる指定子はstrftime
とstrptime
の両方で使えます。
例はdt = datetime(2025, 9, 16, 13, 5, 9, 123456)
とします。
注意
%a/%A(曜日)・%b/%B(月名)はロケール(システムの言語設定)に依存します。
ここでは英語例を示しますが、環境によって出力が異なる場合があります。
年(%Y)/年2桁(%y)
指定子 | 意味 | 例 |
---|---|---|
%Y | 西暦4桁 | 2025 |
%y | 西暦下2桁 | 25 |
%Y
はゼロ埋めされた4桁、西暦を確実に表現したい場合の基本指定子です。
月(%m)/日(%d)
指定子 | 意味 | 例 |
---|---|---|
%m | 月(ゼロ埋め2桁 01–12) | 09 |
%d | 日(ゼロ埋め2桁 01–31) | 16 |
日付の区切り(例:-
や/
)はフォーマット文字列にそのまま書きます。
時(%H)/分(%M)/秒(%S)
指定子 | 意味 | 例 |
---|---|---|
%H | 時(24時間表記 00–23) | 13 |
%M | 分(00–59) | 05 |
%S | 秒(00–59、うるう秒は環境依存) | 09 |
24時間表記は%H
です。
12時間表記の%I
ではありません。
マイクロ秒(%f)
指定子 | 意味 | 例 |
---|---|---|
%f | マイクロ秒(000000–999999) | 123456 |
ログの精度が必要な場合などに使います。
通常の画面表示では省略し、ファイル名や監査ログでは含めると実用的です。
曜日(%a %A)/月名(%b %B)
指定子 | 意味 | 例(英語ロケール) |
---|---|---|
%a | 曜日の省略名 | Tue |
%A | 曜日の完全名 | Tuesday |
%b | 月名の省略名 | Sep |
%B | 月名の完全名 | September |
ロケール依存の出力は人向け表示には便利ですが、機械処理向けデータには不向きです。
データ交換には数字中心の書式(例:%Y-%m-%d
)を推奨します。
参考として、まとめて出力する例を示します。
from datetime import datetime
dt = datetime(2025, 9, 16, 13, 5, 9, 123456)
# 出力はロケール(システムの言語設定)によって異なる場合があります
print("Y:", dt.strftime("%Y"), "y:", dt.strftime("%y"))
print("m:", dt.strftime("%m"), "d:", dt.strftime("%d"))
print("H:", dt.strftime("%H"), "M:", dt.strftime("%M"), "S:", dt.strftime("%S"))
print("f:", dt.strftime("%f"))
print("a:", dt.strftime("%a"), "A:", dt.strftime("%A"))
print("b:", dt.strftime("%b"), "B:", dt.strftime("%B"))
Y: 2025 y: 25
m: 09 d: 16
H: 13 M: 05 S: 09
f: 123456
a: Tue A: Tuesday
b: Sep B: September
コピペで使える日付フォーマット例と変換レシピ(Python)
ここからは用途別に、そのまま貼って使えるコードを用意しました。
「作る」(strftime)と「読む」(strptime)を必ずペアで覚えると、迷いにくくなります。
yyyy-mm-dd(2025-09-16)
from datetime import datetime
dt = datetime(2025, 9, 16, 13, 5, 9)
# 作る
s = dt.strftime("%Y-%m-%d")
print(s) # 2025-09-16
# 読む
parsed = datetime.strptime("2025-09-16", "%Y-%m-%d")
print(parsed.date()) # 2025-09-16
2025-09-16
2025-09-16
区切りがハイフンなら-%m-
のように、そのまま入れるのがポイントです。
yyyy/mm/dd HH:MM:SS(24時間)
from datetime import datetime
dt = datetime(2025, 9, 16, 13, 5, 9)
# 作る
s = dt.strftime("%Y/%m/%d %H:%M:%S")
print(s) # 2025/09/16 13:05:09
# 読む
parsed = datetime.strptime("2025/09/16 13:05:09", "%Y/%m/%d %H:%M:%S")
print(parsed) # 2025-09-16 13:05:09
2025/09/16 13:05:09
2025-09-16 13:05:09
大文字の%M
は分、小文字の%m
は月です。
取り違えに注意します。
mm/dd/yyyy(米国式)
from datetime import datetime
dt = datetime(2025, 9, 16, 13, 5, 9)
# 作る
s = dt.strftime("%m/%d/%Y")
print(s) # 09/16/2025
# 読む
parsed = datetime.strptime("09/16/2025", "%m/%d/%Y")
print(parsed.date()) # 2025-09-16
09/16/2025
2025-09-16
米国式は月/日/年の順です。
国際化する場合はISO 8601(後述)が安全です。
yyyy年mm月dd日(日本語)
from datetime import datetime
dt = datetime(2025, 9, 16)
# 作る(「年」「月」「日」は固定文字としてそのまま書きます)
s = dt.strftime("%Y年%m月%d日")
print(s) # 2025年09月16日
# 読む
parsed = datetime.strptime("2025年09月16日", "%Y年%m月%d日")
print(parsed.date()) # 2025-09-16
2025年09月16日
2025-09-16
曜日名を入れるとロケールの影響を受けます。
機械処理向けには数字だけにするのが無難です。
ISO 8601(YYYY-MM-DDThh:mm:ss)
from datetime import datetime
dt = datetime(2025, 9, 16, 13, 5, 9)
# 作る(1) strftimeで"T"をはさむ
s1 = dt.strftime("%Y-%m-%dT%H:%M:%S")
print(s1) # 2025-09-16T13:05:09
# 作る(2) 便利メソッド: isoformat
s2 = dt.isoformat(timespec="seconds")
print(s2) # 2025-09-16T13:05:09
# 読む(1) fromisoformatで読み戻し
parsed1 = datetime.fromisoformat("2025-09-16T13:05:09")
print(parsed1)
# 読む(2) strptimeでも可
parsed2 = datetime.strptime("2025-09-16T13:05:09", "%Y-%m-%dT%H:%M:%S")
print(parsed2)
2025-09-16T13:05:09
2025-09-16T13:05:09
2025-09-16 13:05:09
2025-09-16 13:05:09
isoformat
/fromisoformat
はISO 8601向けの近道です。
文字列の書式を別の書式に変換
「読む」→「作る」の2段階で任意の書式に変換します。
米国式からISO 8601風に変えてみます。
from datetime import datetime
src = "09/16/2025 13:05:09" # 元の表記(mm/dd/yyyy HH:MM:SS)
dt = datetime.strptime(src, "%m/%d/%Y %H:%M:%S") # まず読む
dst = dt.strftime("%Y-%m-%d %H:%M") # 次に作る(秒を落とす例)
print(dst)
2025-09-16 13:05
秒やミリ秒を落とす/加えるのも、この2段階で柔軟に行えます。
初心者がハマりやすい注意点とエラー対策
%m(月)と%M(分)の取り違え
%mは月、%Mは分です。
取り違えるとエラーにならずに間違った日時が出来上がることがあり、発見が遅れます。
from datetime import datetime
s = "09/16/2025"
# 誤り: 月(%m)であるべきところを分(%M)にしてしまった
wrong = datetime.strptime(s, "%M/%d/%Y")
print(wrong) # 2025-01-16 00:09:00 ← 月が1月になり、"09"は分として解釈されてしまう
# 正解
correct = datetime.strptime(s, "%m/%d/%Y")
print(correct) # 2025-09-16 00:00:00
2025-01-16 00:09:00
2025-09-16 00:00:00
日付だけの文字列でも、誤った指定子は無言で別のフィールドに解釈される場合があります。
レビューやテストで早めに気付けるようにしましょう。
フォーマット不一致によるValueError
区切り文字や桁数が合わないとValueError
になります。
エラーメッセージは有用なので、例外を捕まえて表示すると原因特定が速くなります。
from datetime import datetime
try:
# 文字列はスラッシュなのに、フォーマットはハイフンを指定している
datetime.strptime("2025/09/16", "%Y-%m-%d")
except ValueError as e:
print("エラー:", e)
エラー: time data '2025/09/16' does not match format '%Y-%m-%d'
「入力文字列の見た目」と「フォーマット文字列」を1文字も違えず一致させるのが鉄則です。
0埋め/先頭ゼロの扱い
strftime
の数字は原則ゼロ埋め(例:%m
→09)です。
ゼロなしで出したいときは数値属性を使って整形するのが移植性の高い方法です。
from datetime import datetime
dt = datetime(2025, 9, 6)
# ゼロ埋めの標準出力
print(dt.strftime("%m"), dt.strftime("%d")) # 09 06
# ゼロなし(移植性が高い方法)
print(f"{dt.month}", f"{dt.day}") # 9 6
# 参考: Unix系ではゼロ埋め抑制の%-m, %-dが使える環境もあります(Windowsでは非対応のことがあります)
# print(dt.strftime("%-m"), dt.strftime("%-d")) # 9 6
09 06
9 6
strptime側は多くの環境で「9」も「09」も受け付けますが、環境差が出る余地があるため、入力仕様と一致するフォーマットを用意するのが安全です。
タイムゾーンは対象外(別記事)
本記事はタイムゾーンなしの日時を対象にしています。
ISO 8601の末尾にZ
や+09:00
などのオフセットが付く場合はタイムゾーン対応が必要です。
Pythonではdatetime.timezone
やzoneinfo
、fromisoformat
などが使えますが、詳細は別記事で扱います。
まとめ
日付の相互変換は「読む(strptime)→整える(strftime)」の2ステップを押さえれば実務で困りません。
年%Y
・月%m
・日%d
・時%H
・分%M
・秒%S
・マイクロ秒%f
を中心に、区切り文字をそのまま書くのがコツです。
ロケール依存の曜日や月名は人向けに限定し、データ交換には数字ベースの書式を使いましょう。
最後に%m(月)と%M(分)の取り違えやフォーマット不一致のValueErrorに注意しつつ、ここに示したコピペ例から始めれば、すぐに安全で読みやすい日付処理が書けるようになります。