Skip to content

Python Datetime:Pythonの日付と時刻の完全ガイド

Updated on

Pythonでの日付と時刻の操作は簡単であるべきですが、実際にはそうなることは稀です。CSVファイルから日付文字列をパースする必要がありますが、"01/02/2026"はロケールによって1月2日にも2月1日にもなり得ます。2つのタイムスタンプの差を計算したいのに、一方は文字列でもう一方はUnixエポックです。今月もう10回目のstrftimestrptimeの取り違えです。日付と時刻の操作は、プロダクションコードにおけるバグ、off-by-oneエラー、タイムゾーンの頭痛の種の絶え間ない原因です。

その結果は単なる煩わしさを超えます。財務報告書の間違った日付フォーマットは誤った計算を意味します。タイムゾーンを無視したnaiveなdatetime比較は、cronジョブの重複を引き起こします。timedeltaの計算ミスは、顧客に30日ではなく31日分を請求します。

Pythonの組み込みdatetimeモジュールは、クリーンで一貫性のあるAPIでこれらの問題を解決します。日付、時刻、タイムスタンプ、期間のためのクラスを提供します。パターンを学べば -- 特にstrftimestrptimeの違いを理解すれば -- サードパーティライブラリなしであらゆる日付操作を処理できます。

📚

現在の日付と時刻を取得する

最も一般的な出発点は、現在の日付と時刻を取得することです。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.123456

datetime.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:00

Datetimeオブジェクトの作成

個々のコンポーネントまたは既存のデータから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:45

strftimeで日付をフォーマットする

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フォーマットコードリファレンス

コード意味
%Y4桁の年2026
%y2桁の年26
%mゼロ埋めの月03
%B月のフルネームMarch
%b月の略称Mar
%dゼロ埋めの日15
%A曜日のフルネームSunday
%a曜日の略称Sun
%H時間(24時間、ゼロ埋め)09
%I時間(12時間、ゼロ埋め)09
%M分(ゼロ埋め)05
%S秒(ゼロ埋め)07
%pAM/PMAM
%fマイクロ秒(6桁にゼロ埋め)000000
%zUTCオフセット(+HHMMまたは-HHMM)+0000
%Zタイムゾーン名UTC
%j年間通算日(001-366)074
%%リテラルの%文字%

よく使われるフォーマットパターン

パターンフォーマット文字列出力
ISO 8601%Y-%m-%dT%H:%M:%S2026-03-15T09:05:07
米国日付%m/%d/%Y03/15/2026
欧州日付%d/%m/%Y15/03/2026
読みやすい日付%B %d, %YMarch 15, 2026
ログのタイムスタンプ%Y-%m-%d %H:%M:%S2026-03-15 09:05:07
12時間表記%I:%M:%S %p09:05:07 AM
コンパクト日付%Y%m%d20260315
ファイル安全なタイムスタンプ%Y%m%d_%H%M%S20260315_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:00

timedeltaを使った日付演算

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.0

timedeltaコンストラクタのパラメータ

パラメータ説明
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)

すべてのパラメータを組み合わせることができます。内部的に、timedeltadayssecondsmicrosecondsのみを保存します。他はすべて変換されます。

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:00

zoneinfoの使用(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:00

NaiveとAwareのDatetime

特徴NaiveAware
タイムゾーン情報ありいいえはい
ゾーン間比較で安全いいえはい
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: 19

JupyterでDatetimeを実験する

日付と時刻の操作はインタラクティブな実験から恩恵を受けます。CSVから一貫性のない日付フォーマットをパースしたり、タイムゾーン変換をデバッグしたりする際に、ノートブックのセルで各ステップをテストできることで大幅な時間を節約できます。

RunCell (opens in a new tab)はJupyterノートブック内で直接動作するAIエージェントです。datetimeオブジェクトを検査し、データに適したstrftime/strptimeフォーマットコードを提案し、タイムゾーン変換の問題をリアルタイムでデバッグするのを支援します。

strftime vs strptime:クイック比較

strftimestrptime
正式名称String Format TimeString 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:00

FAQ

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)weekshoursminutessecondsもパラメータとして使用できます。減算も同じように機能します: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 ZoneInfodatetime.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)を基準点として開始し、ユーザーに表示する際にのみローカルタイムゾーンに変換してください。

📚