Python Datetime:Pythonの日付と時刻の完全ガイド
Updated on
Pythonでの日付と時刻の操作は簡単であるべきですが、実際にはそうなることは稀です。CSVファイルから日付文字列をパースする必要がありますが、"01/02/2026"はロケールによって1月2日にも2月1日にもなり得ます。2つのタイムスタンプの差を計算したいのに、一方は文字列でもう一方はUnixエポックです。今月もう10回目のstrftimeとstrptimeの取り違えです。日付と時刻の操作は、プロダクションコードにおけるバグ、off-by-oneエラー、タイムゾーンの頭痛の種の絶え間ない原因です。
その結果は単なる煩わしさを超えます。財務報告書の間違った日付フォーマットは誤った計算を意味します。タイムゾーンを無視したnaiveなdatetime比較は、cronジョブの重複を引き起こします。timedeltaの計算ミスは、顧客に30日ではなく31日分を請求します。
Pythonの組み込みdatetimeモジュールは、クリーンで一貫性のあるAPIでこれらの問題を解決します。日付、時刻、タイムスタンプ、期間のためのクラスを提供します。パターンを学べば -- 特にstrftimeとstrptimeの違いを理解すれば -- サードパーティライブラリなしであらゆる日付操作を処理できます。
現在の日付と時刻を取得する
最も一般的な出発点は、現在の日付と時刻を取得することです。datetimeモジュールはこれを行うためのいくつかの方法を提供します。
from datetime import datetime, date
# 現在の日付と時刻
now = datetime.now()
print(now) # 2026-02-10 14:30:45.123456
# 現在の日付のみ
today = date.today()
print(today) # 2026-02-10
# datetime.today()はdatetime.now()に似ていますが、タイムゾーンサポートなし
now_alt = datetime.today()
print(now_alt) # 2026-02-10 14:30:45.123456datetime.now()とdatetime.today()の違いは微妙ですが重要です。datetime.now()はタイムゾーン対応のdatetimeのためのオプションのtzパラメータを受け入れます。datetime.today()は受け入れません。ほとんどのコードではdatetime.now()を使用してください。
from datetime import datetime
from zoneinfo import ZoneInfo
# タイムゾーン対応の現在時刻
utc_now = datetime.now(tz=ZoneInfo("UTC"))
print(utc_now) # 2026-02-10 14:30:45.123456+00:00
tokyo_now = datetime.now(tz=ZoneInfo("Asia/Tokyo"))
print(tokyo_now) # 2026-02-10 23:30:45.123456+09:00Datetimeオブジェクトの作成
個々のコンポーネントまたは既存のデータからdatetimeオブジェクトを作成できます。
from datetime import datetime, date, time
# 年、月、日、時、分、秒から
dt = datetime(2026, 3, 15, 9, 30, 0)
print(dt) # 2026-03-15 09:30:00
# 日付のみ
d = date(2026, 12, 25)
print(d) # 2026-12-25
# 時刻のみ
t = time(14, 30, 0)
print(t) # 14:30:00
# 日付と時刻を結合
combined = datetime.combine(d, t)
print(combined) # 2026-12-25 14:30:00既存のdatetimeからコンポーネントを抽出することもできます。
from datetime import datetime
dt = datetime(2026, 3, 15, 9, 30, 45)
print(dt.year) # 2026
print(dt.month) # 3
print(dt.day) # 15
print(dt.hour) # 9
print(dt.minute) # 30
print(dt.second) # 45
print(dt.weekday()) # 6 (日曜日、月曜日=0)
print(dt.isoformat()) # 2026-03-15T09:30:45strftimeで日付をフォーマットする
strftimeは「string format time」(文字列フォーマット時間)の略です。datetimeオブジェクトをフォーマットされた文字列に変換します。日付コンポーネントに置き換えられるディレクティブを含むフォーマット文字列を渡します。
from datetime import datetime
dt = datetime(2026, 3, 15, 9, 5, 7)
# 一般的なフォーマット
print(dt.strftime("%Y-%m-%d")) # 2026-03-15
print(dt.strftime("%d/%m/%Y")) # 15/03/2026
print(dt.strftime("%B %d, %Y")) # March 15, 2026
print(dt.strftime("%Y-%m-%d %H:%M:%S")) # 2026-03-15 09:05:07
print(dt.strftime("%I:%M %p")) # 09:05 AM
print(dt.strftime("%A, %B %d, %Y")) # Sunday, March 15, 2026覚え方:strftime = string from time(datetimeから文字列へ)。
strftimeフォーマットコードリファレンス
| コード | 意味 | 例 |
|---|---|---|
%Y | 4桁の年 | 2026 |
%y | 2桁の年 | 26 |
%m | ゼロ埋めの月 | 03 |
%B | 月のフルネーム | March |
%b | 月の略称 | Mar |
%d | ゼロ埋めの日 | 15 |
%A | 曜日のフルネーム | Sunday |
%a | 曜日の略称 | Sun |
%H | 時間(24時間、ゼロ埋め) | 09 |
%I | 時間(12時間、ゼロ埋め) | 09 |
%M | 分(ゼロ埋め) | 05 |
%S | 秒(ゼロ埋め) | 07 |
%p | AM/PM | AM |
%f | マイクロ秒(6桁にゼロ埋め) | 000000 |
%z | UTCオフセット(+HHMMまたは-HHMM) | +0000 |
%Z | タイムゾーン名 | UTC |
%j | 年間通算日(001-366) | 074 |
%% | リテラルの%文字 | % |
よく使われるフォーマットパターン
| パターン | フォーマット文字列 | 出力 |
|---|---|---|
| ISO 8601 | %Y-%m-%dT%H:%M:%S | 2026-03-15T09:05:07 |
| 米国日付 | %m/%d/%Y | 03/15/2026 |
| 欧州日付 | %d/%m/%Y | 15/03/2026 |
| 読みやすい日付 | %B %d, %Y | March 15, 2026 |
| ログのタイムスタンプ | %Y-%m-%d %H:%M:%S | 2026-03-15 09:05:07 |
| 12時間表記 | %I:%M:%S %p | 09:05:07 AM |
| コンパクト日付 | %Y%m%d | 20260315 |
| ファイル安全なタイムスタンプ | %Y%m%d_%H%M%S | 20260315_090507 |
strptimeで文字列をパースする
strptimeは「string parse time」(文字列パース時間)の略です。strftimeの逆で -- 文字列をdatetimeオブジェクトに変換します。文字列とそれに対応するフォーマットを指定します。
from datetime import datetime
# さまざまな日付文字列フォーマットをパース
dt1 = datetime.strptime("2026-03-15", "%Y-%m-%d")
print(dt1) # 2026-03-15 00:00:00
dt2 = datetime.strptime("15/03/2026", "%d/%m/%Y")
print(dt2) # 2026-03-15 00:00:00
dt3 = datetime.strptime("March 15, 2026 09:30 AM", "%B %d, %Y %I:%M %p")
print(dt3) # 2026-03-15 09:30:00
dt4 = datetime.strptime("2026-03-15T09:30:00", "%Y-%m-%dT%H:%M:%S")
print(dt4) # 2026-03-15 09:30:00覚え方:strptime = string parse time(文字列からdatetimeへ)。
パースエラーの処理
文字列がフォーマットに一致しない場合、PythonはValueErrorを発生させます。ユーザー入力や外部データをパースする際は、常にstrptimeの呼び出しをエラー処理でラップしてください。
from datetime import datetime
def safe_parse_date(date_string, fmt="%Y-%m-%d"):
"""Parse a date string safely, returning None on failure."""
try:
return datetime.strptime(date_string, fmt)
except ValueError as e:
print(f"Could not parse '{date_string}': {e}")
return None
# Valid input
print(safe_parse_date("2026-03-15")) # 2026-03-15 00:00:00
# Invalid input
print(safe_parse_date("15-03-2026")) # Could not parse '15-03-2026': ...
print(safe_parse_date("not a date")) # Could not parse 'not a date': ...複数フォーマットのパース
予測できないフォーマットで日付を受け取る場合は、複数のパターンを試します。
from datetime import datetime
def parse_flexible_date(date_string):
"""Try multiple date formats and return the first match."""
formats = [
"%Y-%m-%d",
"%d/%m/%Y",
"%m/%d/%Y",
"%B %d, %Y",
"%b %d, %Y",
"%Y-%m-%dT%H:%M:%S",
"%Y-%m-%d %H:%M:%S",
]
for fmt in formats:
try:
return datetime.strptime(date_string, fmt)
except ValueError:
continue
raise ValueError(f"No matching format found for '{date_string}'")
print(parse_flexible_date("2026-03-15")) # 2026-03-15 00:00:00
print(parse_flexible_date("March 15, 2026")) # 2026-03-15 00:00:00
print(parse_flexible_date("15/03/2026")) # 2026-03-15 00:00:00timedeltaを使った日付演算
timedeltaクラスは期間 -- 2つの日付または時刻の差を表します。timedeltaオブジェクトを加算または減算して、日付を前後に移動できます。
from datetime import datetime, timedelta
now = datetime(2026, 2, 10, 12, 0, 0)
# 日数を加算
tomorrow = now + timedelta(days=1)
print(tomorrow) # 2026-02-11 12:00:00
# 日数を減算
last_week = now - timedelta(weeks=1)
print(last_week) # 2026-02-03 12:00:00
# 時間と分を加算
later = now + timedelta(hours=5, minutes=30)
print(later) # 2026-02-10 17:30:00
# 複数の単位を組み合わせる
future = now + timedelta(weeks=2, days=3, hours=6)
print(future) # 2026-02-27 18:00:00時間差の計算
あるdatetimeから別のdatetimeを減算すると、timedeltaが返されます。
from datetime import datetime
start = datetime(2026, 1, 1)
end = datetime(2026, 12, 31)
diff = end - start
print(diff) # 364 days, 0:00:00
print(diff.days) # 364
print(diff.total_seconds()) # 31449600.0timedeltaコンストラクタのパラメータ
| パラメータ | 説明 | 例 |
|---|---|---|
weeks | 週数 | timedelta(weeks=2) = 14日 |
days | 日数 | timedelta(days=30) |
hours | 時間数 | timedelta(hours=12) |
minutes | 分数 | timedelta(minutes=45) |
seconds | 秒数 | timedelta(seconds=120) |
milliseconds | ミリ秒数 | timedelta(milliseconds=500) |
microseconds | マイクロ秒数 | timedelta(microseconds=1000) |
すべてのパラメータを組み合わせることができます。内部的に、timedeltaはdays、seconds、microsecondsのみを保存します。他はすべて変換されます。
from datetime import timedelta
delta = timedelta(weeks=1, days=2, hours=3, minutes=30, seconds=45)
print(delta) # 9 days, 3:30:45
print(delta.days) # 9
print(delta.seconds) # 12645 (3*3600 + 30*60 + 45)
print(delta.total_seconds()) # 790245.0日付の比較
Datetimeオブジェクトは標準のすべての比較演算子をサポートします。これにより、日付のソートとフィルタリングが簡単になります。
from datetime import datetime
dt1 = datetime(2026, 1, 1)
dt2 = datetime(2026, 6, 15)
dt3 = datetime(2026, 12, 31)
print(dt1 < dt2) # True
print(dt3 > dt2) # True
print(dt1 == dt2) # False
print(dt1 != dt2) # True日付のソート
from datetime import datetime
dates = [
datetime(2026, 12, 25),
datetime(2026, 1, 1),
datetime(2026, 7, 4),
datetime(2026, 2, 14),
]
sorted_dates = sorted(dates)
for d in sorted_dates:
print(d.strftime("%B %d, %Y"))
# January 01, 2026
# February 14, 2026
# July 04, 2026
# December 25, 2026タイムスタンプの操作
Unixタイムスタンプは1970年1月1日(Unixエポック)からの秒数を表します。datetimeモジュールはタイムスタンプとdatetimeオブジェクト間の変換ができます。
from datetime import datetime, timezone
# Datetimeからタイムスタンプへ
dt = datetime(2026, 3, 15, 9, 30, 0)
ts = dt.timestamp()
print(ts) # 1773814200.0 (ローカルタイムゾーンに依存)
# タイムスタンプからDatetimeへ(タイムゾーン対応、推奨)
dt_aware = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt_aware) # 2026-03-15 01:30:00+00:00重要: タイムゾーンなしのdatetime.fromtimestamp()はローカル時刻を返します。UTCの場合は、常にtz=timezone.utcを渡してください。
タイムゾーンの処理
Naive datetime(タイムゾーン情報なし)はバグの一般的な原因です。Pythonはタイムゾーン対応のdatetimeのために2つの組み込みアプローチを提供します。
datetime.timezoneの使用(組み込み)
timezoneクラスは固定UTCオフセットを処理します。
from datetime import datetime, timezone, timedelta
# UTC
utc_now = datetime.now(timezone.utc)
print(utc_now) # 2026-02-10 14:30:00+00:00
# 固定オフセット(例:インドのUTC+5:30)
ist = timezone(timedelta(hours=5, minutes=30))
india_time = datetime.now(ist)
print(india_time) # 2026-02-10 20:00:00+05:30
# タイムゾーン間の変換
utc_time = datetime(2026, 3, 15, 12, 0, 0, tzinfo=timezone.utc)
eastern = timezone(timedelta(hours=-5))
eastern_time = utc_time.astimezone(eastern)
print(eastern_time) # 2026-03-15 07:00:00-05:00zoneinfoの使用(Python 3.9+)
夏時間を正しく処理する名前付きタイムゾーンには、zoneinfoモジュールを使用します。
from datetime import datetime
from zoneinfo import ZoneInfo
# 名前付きタイムゾーン
utc = ZoneInfo("UTC")
eastern = ZoneInfo("America/New_York")
tokyo = ZoneInfo("Asia/Tokyo")
# タイムゾーン対応のdatetimeを作成
dt = datetime(2026, 7, 15, 12, 0, 0, tzinfo=utc)
print(dt) # 2026-07-15 12:00:00+00:00
# 他のタイムゾーンに変換
print(dt.astimezone(eastern)) # 2026-07-15 08:00:00-04:00 (EDT)
print(dt.astimezone(tokyo)) # 2026-07-15 21:00:00+09:00NaiveとAwareのDatetime
| 特徴 | Naive | Aware |
|---|---|---|
| タイムゾーン情報あり | いいえ | はい |
| ゾーン間比較で安全 | いいえ | はい |
datetime.now()で作成 | はい | いいえ(tzを渡さない限り) |
| 演算で混在可能 | 他のnaiveとのみ | 他のawareとのみ |
| 本番環境で推奨 | いいえ | はい |
naiveなdatetimeとawareなdatetimeを比較または減算することはできません。PythonはTypeErrorを発生させます。
実用的な例
人の年齢を計算する
from datetime import date
def calculate_age(birth_date):
"""Calculate age in years from a birth date."""
today = date.today()
age = today.year - birth_date.year
if (today.month, today.day) < (birth_date.month, birth_date.day):
age -= 1
return age
birthday = date(1995, 8, 20)
print(f"Age: {calculate_age(birthday)} years") # Age: 30 years (as of Feb 2026)日付範囲を生成する
from datetime import date, timedelta
def date_range(start, end, step_days=1):
"""Generate dates from start to end (inclusive)."""
current = start
while current <= end:
yield current
current += timedelta(days=step_days)
start = date(2026, 2, 1)
end = date(2026, 2, 7)
for d in date_range(start, end):
print(d.strftime("%A, %B %d"))2つの日付間の営業日数を数える
from datetime import date, timedelta
def business_days_between(start, end):
"""Count weekdays (Mon-Fri) between two dates, excluding endpoints."""
count = 0
current = start + timedelta(days=1)
while current < end:
if current.weekday() < 5: # 0=Mon, 4=Fri
count += 1
current += timedelta(days=1)
return count
start = date(2026, 2, 1)
end = date(2026, 2, 28)
print(f"Business days: {business_days_between(start, end)}") # Business days: 19JupyterでDatetimeを実験する
日付と時刻の操作はインタラクティブな実験から恩恵を受けます。CSVから一貫性のない日付フォーマットをパースしたり、タイムゾーン変換をデバッグしたりする際に、ノートブックのセルで各ステップをテストできることで大幅な時間を節約できます。
RunCell (opens in a new tab)はJupyterノートブック内で直接動作するAIエージェントです。datetimeオブジェクトを検査し、データに適したstrftime/strptimeフォーマットコードを提案し、タイムゾーン変換の問題をリアルタイムでデバッグするのを支援します。
strftime vs strptime:クイック比較
| strftime | strptime | |
|---|---|---|
| 正式名称 | String Format Time | String Parse Time |
| 方向 | datetime -> 文字列 | 文字列 -> datetime |
| 呼び出し対象 | datetimeオブジェクト | datetimeクラス |
| 構文 | dt.strftime("%Y-%m-%d") | datetime.strptime(s, "%Y-%m-%d") |
| 戻り値 | フォーマットされた文字列 | datetimeオブジェクト |
| 例外 | なし | フォーマット不一致時にValueError |
| 使用例 | 表示、ログ、ファイル名 | CSV、APIレスポンス、ユーザー入力のパース |
from datetime import datetime
# strftime: datetime -> string
dt = datetime(2026, 3, 15, 9, 30)
formatted = dt.strftime("%B %d, %Y at %I:%M %p")
print(formatted) # March 15, 2026 at 09:30 AM
# strptime: string -> datetime
parsed = datetime.strptime("March 15, 2026 at 09:30 AM", "%B %d, %Y at %I:%M %p")
print(parsed) # 2026-03-15 09:30:00FAQ
Pythonで現在の日付と時刻を取得するには?
datetimeモジュールのdatetime.now()を使用します。日付のみの場合はdate.today()を使用します。タイムゾーン対応の現在時刻の場合は、タイムゾーンを渡します:datetime.now(tz=timezone.utc)。これらは標準的なアプローチであり、サードパーティライブラリは必要ありません。
Pythonのstrftimeとstrptimeの違いは?
strftimeはdatetimeオブジェクトをフォーマットされた文字列に変換します(string from time)。strptimeは文字列をパースしてdatetimeオブジェクトに変換します(string parse time)。strftimeは文字列を出力し、strptimeは文字列を入力すると覚えてください。両方とも%Y、%m、%dのような同じフォーマットコードを使用します。
Pythonで日付に日数を追加するには?
timedeltaクラスを使用します。datetimeからインポートし、日付に追加します:new_date = old_date + timedelta(days=7)。weeks、hours、minutes、secondsもパラメータとして使用できます。減算も同じように機能します:past_date = today - timedelta(days=30)。
Pythonで文字列をdatetimeに変換するには?
datetime.strptime(string, format)を使用します。入力に一致するフォーマット文字列を提供する必要があります。例えば、datetime.strptime("2026-03-15", "%Y-%m-%d")はISO日付をパースします。文字列がフォーマットに一致しない場合、PythonはValueErrorを発生させるので、外部データの場合はtry/exceptブロックで呼び出しをラップしてください。
Python datetimeでタイムゾーンを処理するには?
Python 3.9以降では、組み込みのzoneinfoモジュールを使用します:from zoneinfo import ZoneInfo。datetime.now(tz=ZoneInfo("UTC"))でタイムゾーン対応のdatetimeを作成し、dt.astimezone(ZoneInfo("America/New_York"))でゾーン間を変換します。固定UTCオフセットにはdatetime.timezone(timedelta(hours=N))を使用します。本番コードではnaiveなdatetimeを避けてください。
まとめ
Pythonのdatetimeモジュールは日付と時刻の操作に必要なすべてを提供します:日付の作成、表示用のフォーマット、文字列からのパース、演算の実行、タイムゾーンの処理。主要なパターンは一度学べば一貫性があり予測可能です。
核心的な区別を覚えてください:strftimeはdatetimeを文字列にフォーマットし、strptimeは文字列をdatetimeにパースします。日付演算にはtimedeltaを使用します。適切なタイムゾーン処理にはzoneinfo(Python 3.9+)を使用します。微妙な比較バグを避けるため、本番コードではdatetimeをタイムゾーン対応に保ってください。
ほとんどのプロジェクトでは、組み込みのdatetimeモジュールで十分です。モダンPythonではpytzは必要ありません -- zoneinfoが名前付きタイムゾーンをネイティブに処理します。datetime.now(tz=timezone.utc)を基準点として開始し、ユーザーに表示する際にのみローカルタイムゾーンに変換してください。