Python ISO 8601形式とdatetime変換方法【完全ガイド】

ISO 8601は国際標準の日時表記形式で、Web APIやデータ交換でよく使用されます。この記事では、PythonでISO 8601形式とdatetimeオブジェクト間の相互変換を詳しく解説します。

ISO 8601形式とは

ISO 8601形式はYYYY-MM-DDTHH:MM:SS.ffffffZのような形式で、国際的に標準化された日時表記です。

# ISO 8601形式の例
# 2024-01-15T14:30:25.123456Z
# 2024-01-15T14:30:25+09:00
# 2024-01-15T14:30:25.123Z

datetimeからISO 8601形式への変換

基本的な変換(isoformat()使用)

from datetime import datetime, timezone

# 現在時刻をISO形式に変換
now = datetime.now()
iso_string = now.isoformat()
print(iso_string)  # 2024-01-15T14:30:25.123456

# UTC時刻をISO形式に変換
utc_now = datetime.now(timezone.utc)
iso_utc = utc_now.isoformat()
print(iso_utc)  # 2024-01-15T05:30:25.123456+00:00

タイムゾーンを含むISO形式

from datetime import datetime, timezone, timedelta

# JST(日本標準時)でISO形式を生成
jst = timezone(timedelta(hours=9))
dt_jst = datetime.now(jst)
print(dt_jst.isoformat())  # 2024-01-15T14:30:25.123456+09:00

# UTC形式(Zサフィックス付き)
utc_dt = datetime.now(timezone.utc)
print(utc_dt.isoformat().replace('+00:00', 'Z'))  # 2024-01-15T05:30:25.123456Z

カスタムフォーマット

from datetime import datetime

def to_iso8601(dt, include_microseconds=True):
    if include_microseconds:
        return dt.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
    else:
        return dt.strftime('%Y-%m-%dT%H:%M:%SZ')

now = datetime.utcnow()
print(to_iso8601(now, True))   # 2024-01-15T05:30:25.123456Z
print(to_iso8601(now, False))  # 2024-01-15T05:30:25Z

ISO 8601形式からdatetimeへの変換

Python 3.7以降のfromisoformat()使用

from datetime import datetime

# 基本的なISO形式の解析
iso_str = '2024-01-15T14:30:25.123456'
dt = datetime.fromisoformat(iso_str)
print(dt)  # 2024-01-15 14:30:25.123456

# タイムゾーン付きISO形式の解析
iso_tz_str = '2024-01-15T14:30:25+09:00'
dt_tz = datetime.fromisoformat(iso_tz_str)
print(dt_tz)  # 2024-01-15 14:30:25+09:00

Zサフィックスの処理

from datetime import datetime, timezone

def parse_iso8601(iso_string):
    # Zサフィックスを+00:00に置換
    if iso_string.endswith('Z'):
        iso_string = iso_string[:-1] + '+00:00'
    
    return datetime.fromisoformat(iso_string)

# 使用例
utc_str = '2024-01-15T05:30:25Z'
dt = parse_iso8601(utc_str)
print(dt)  # 2024-01-15 05:30:25+00:00

strptime()を使用した解析

from datetime import datetime, timezone

def parse_iso_strptime(iso_string):
    formats = [
        '%Y-%m-%dT%H:%M:%S.%fZ',      # マイクロ秒付きUTC
        '%Y-%m-%dT%H:%M:%SZ',         # UTC
        '%Y-%m-%dT%H:%M:%S.%f',       # マイクロ秒付きローカル
        '%Y-%m-%dT%H:%M:%S',          # ローカル
    ]
    
    for fmt in formats:
        try:
            dt = datetime.strptime(iso_string, fmt)
            if iso_string.endswith('Z'):
                dt = dt.replace(tzinfo=timezone.utc)
            return dt
        except ValueError:
            continue
    
    raise ValueError(f"無効なISO 8601形式: {iso_string}")

# 使用例
result = parse_iso_strptime('2024-01-15T14:30:25Z')
print(result)

様々なISO形式のパターン

日付のみの処理

from datetime import date, datetime

# 日付のみのISO形式
date_str = '2024-01-15'
dt = datetime.fromisoformat(date_str)
print(dt)  # 2024-01-15 00:00:00

# dateオブジェクトとしての処理
date_obj = date.fromisoformat(date_str)
print(date_obj)  # 2024-01-15

週番号形式(ISO週)

from datetime import datetime, date

def iso_week_to_date(year, week, weekday=1):
    """ISO週番号から日付を取得"""
    jan4 = date(year, 1, 4)
    start_week = jan4 - timedelta(days=jan4.weekday())
    target_date = start_week + timedelta(weeks=week-1, days=weekday-1)
    return target_date

# 2024年の第3週の月曜日
result = iso_week_to_date(2024, 3, 1)
print(result)

実用的な応用例

API レスポンスの処理

import json
from datetime import datetime

def process_api_response(json_data):
    """APIレスポンスのISO形式日付を処理"""
    data = json.loads(json_data)
    
    # ISO形式の文字列をdatetimeに変換
    if 'created_at' in data:
        data['created_at'] = datetime.fromisoformat(data['created_at'].replace('Z', '+00:00'))
    
    return data

# 使用例
api_json = '{"id": 1, "created_at": "2024-01-15T14:30:25Z"}'
result = process_api_response(api_json)
print(result['created_at'])

ログファイルの日時変換

from datetime import datetime
import re

def convert_log_timestamps(log_line):
    """ログ行のISO形式タイムスタンプをローカル時刻に変換"""
    iso_pattern = r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})'
    
    def replace_timestamp(match):
        iso_str = match.group()
        dt = datetime.fromisoformat(iso_str.replace('Z', '+00:00'))
        return dt.strftime('%Y-%m-%d %H:%M:%S')
    
    return re.sub(iso_pattern, replace_timestamp, log_line)

# 使用例
log = "2024-01-15T14:30:25Z ERROR: Something went wrong"
converted = convert_log_timestamps(log)
print(converted)  # 2024-01-15 14:30:25 ERROR: Something went wrong

バッチ処理での日時変換

from datetime import datetime

def batch_convert_iso_dates(date_list):
    """ISO形式の日付リストを一括変換"""
    converted = []
    errors = []
    
    for iso_date in date_list:
        try:
            dt = datetime.fromisoformat(iso_date.replace('Z', '+00:00'))
            converted.append(dt)
        except ValueError as e:
            errors.append((iso_date, str(e)))
    
    return converted, errors

# 使用例
iso_dates = [
    '2024-01-15T14:30:25Z',
    '2024-01-16T10:00:00+09:00',
    'invalid-date',
    '2024-01-17T08:45:30.123Z'
]

success, failed = batch_convert_iso_dates(iso_dates)
print(f"成功: {len(success)}件")
print(f"失敗: {len(failed)}件")

パフォーマンスの考慮

大量データ処理での最適化

from datetime import datetime
import time

# パフォーマンステスト用のデータ
iso_dates = ['2024-01-15T14:30:25Z'] * 10000

# fromisoformat()の性能
start = time.time()
for iso_str in iso_dates:
    dt = datetime.fromisoformat(iso_str.replace('Z', '+00:00'))
print(f"fromisoformat: {time.time() - start:.3f}秒")

# strptime()の性能
start = time.time()
for iso_str in iso_dates:
    dt = datetime.strptime(iso_str, '%Y-%m-%dT%H:%M:%SZ')
print(f"strptime: {time.time() - start:.3f}秒")

エラーハンドリング

from datetime import datetime

def safe_iso_parse(iso_string):
    """安全なISO形式解析"""
    try:
        # Zサフィックスの処理
        if iso_string.endswith('Z'):
            iso_string = iso_string[:-1] + '+00:00'
        
        return datetime.fromisoformat(iso_string)
    
    except ValueError as e:
        print(f"ISO形式解析エラー: {iso_string} - {e}")
        return None

# 使用例
test_dates = [
    '2024-01-15T14:30:25Z',
    '2024-13-45T25:70:80Z',  # 無効な日付
    '2024-01-15T14:30:25+09:00'
]

for date_str in test_dates:
    result = safe_iso_parse(date_str)
    if result:
        print(f"成功: {result}")

まとめ

  • 変換方法
    • datetime → ISO: isoformat()
    • ISO → datetime: fromisoformat() (Python 3.7+)
  • Zサフィックス+00:00に置換して処理
  • エラーハンドリングValueErrorの適切な処理が重要
  • パフォーマンスfromisoformat()strptime()より高速
  • 実用例:API処理、ログ変換、バッチ処理など

ISO 8601形式の理解と適切な変換処理により、国際的なシステム間での日時データ交換が効率的に行えます。

らくらくPython塾 – 読むだけでマスター

■プロンプトだけでオリジナルアプリを開発・公開してみた!!

■AI時代の第一歩!「AI駆動開発コース」はじめました!

テックジム東京本校で先行開始。

■テックジム東京本校

「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。

<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。

<月1開催>放送作家による映像ディレクター養成講座

<オンライン無料>ゼロから始めるPython爆速講座