Tutorial

Python タイムスタンプ処理ガイド

はじめに

Python には、日付とタイムスタンプを操作するための 2 つの主要なモジュールが用意されています。高レベルの日付操作用の datetime と、低レベルのタイムスタンプ操作用の time です。 Python でタイムスタンプを適切に使用する方法を理解することは、データ処理、API 統合、および時間ベースのアプリケーションにとって不可欠です。このガイドでは、タイムスタンプの基礎、変換、タイムゾーンの処理、およびベスト プラクティスについて説明します。

現在のタイムスタンプを取得する

timeモジュールの使用

import time

# Get current Unix timestamp (seconds since epoch)
now_seconds = time.time()
print(now_seconds)  # e.g., 1704672000.123456

# Get current timestamp as integer
now_int = int(time.time())
print(now_int)  # e.g., 1704672000

# Get current time in milliseconds
now_ms = int(time.time() * 1000)
print(now_ms)  # e.g., 1704672000123

datetime モジュールの使用

from datetime import datetime

# Get current UTC datetime
now_utc = datetime.utcnow()
print(now_utc)  # 2024-01-08 00:00:00.123456

# Get current local datetime
now_local = datetime.now()
print(now_local)  # 2024-01-07 19:00:00.123456 (if EST)

# Get timestamp from datetime
timestamp = now_utc.timestamp()
print(timestamp)  # e.g., 1704672000.123456

ベスト プラクティス: UTC タイムスタンプには datetime.utcnow() を使用し、ローカル タイムスタンプには datetime.now() を使用します。タイムゾーンについては常に明示的にしてください。

タイムスタンプから日時を作成する

Unix タイムスタンプから (秒)

from datetime import datetime

# Create datetime from Unix timestamp (seconds)
dt = datetime.fromtimestamp(1704672000)
print(dt)  # 2024-01-07 19:00:00 (local timezone)

# Create UTC datetime from Unix timestamp
dt_utc = datetime.utcfromtimestamp(1704672000)
print(dt_utc)  # 2024-01-08 00:00:00+00:00 (UTC)

Unix タイムスタンプから (ミリ秒)

from datetime import datetime

# Convert milliseconds to datetime
ts_ms = 1704672000123
dt = datetime.fromtimestamp(ts_ms / 1000)
print(dt)  # 2024-01-08 00:00:00.123000

重要: datetime.fromtimestamp() はローカル タイムゾーンを使用します。 UTC には datetime.utcfromtimestamp() を使用します。

開始日コンポーネント

from datetime import datetime

# Create from year, month, day, hour, minute, second
dt = datetime(2024, 1, 8, 14, 30, 45)
print(dt)  # 2024-01-08 14:30:45

# Create date only (time defaults to midnight)
dt_date = datetime(2024, 1, 8)
print(dt_date)  # 2024-01-08 00:00:00

# Create time only (date defaults to 1900-01-01)
from datetime import time
t = time(14, 30, 45)
print(t)  # 14:30:45

Python 範囲: datetime オブジェクトは 1 年から 9999 年までを表すことができます。

日時をタイムスタンプに変換する

timestamp() メソッドの使用

from datetime import datetime

# Convert datetime to Unix timestamp (seconds)
dt = datetime(2024, 1, 8, 14, 30, 45)
timestamp = dt.timestamp()
print(timestamp)  # e.g., 1704672654.0

# Convert UTC datetime to timestamp
dt_utc = datetime(2024, 1, 8, 14, 30, 45, tzinfo=timezone.utc)
timestamp_utc = dt_utc.timestamp()
print(timestamp_utc)  # e.g., 1704695045.0

UTC に Calendar.timegm() を使用する

import calendar
from datetime import datetime

# Convert UTC datetime to timestamp (naive datetime assumed UTC)
dt = datetime(2024, 1, 8, 14, 30, 45)
timestamp_utc = calendar.timegm(dt.timetuple())
print(timestamp_utc)  # e.g., 1704695045

# More reliable than timestamp() for UTC naive datetimes

使用例: calendar.timegm() は、単純な日時からの UTC タイムスタンプを操作する場合に便利です。

日付の算術演算

時間の加算と減算

from datetime import datetime, timedelta

# Add 7 days
dt = datetime(2024, 1, 8)
future = dt + timedelta(days=7)
print(future)  # 2024-01-15 00:00:00

# Subtract 1 hour
past = dt - timedelta(hours=1)
print(past)  # 2024-01-07 23:00:00

# Add 2 hours and 30 minutes
dt = datetime(2024, 1, 8, 10, 0, 0)
dt = dt + timedelta(hours=2, minutes=30)
print(dt)  # 2024-01-08 12:30:00

# Add negative timedelta (subtract)
dt = datetime(2024, 1, 8)
dt = dt + timedelta(days=-1)
print(dt)  # 2024-01-07 00:00:00

期間の計算

from datetime import datetime

# Calculate duration between two datetimes
dt1 = datetime(2024, 1, 8, 10, 0, 0)
dt2 = datetime(2024, 1, 8, 18, 0, 0)

duration = dt2 - dt1
print(duration)  # 8:00:00

# Extract duration components
print(duration.days)    # 0
print(duration.seconds)  # 28800 (8 hours)
print(duration.total_seconds())  # 28800.0

# Calculate in hours
hours = duration.total_seconds() / 3600
print(f"Duration: {hours} hours")  # Duration: 8.0 hours

営業日の計算

from datetime import datetime, timedelta

def add_business_days(start_date, days):
    """Add business days to a date (excludes weekends)"""
    result = start_date
    added_days = 0

    while added_days < days:
        result += timedelta(days=1)
        if result.weekday() < 5:  # Monday=0, Friday=4
            added_days += 1

    return result

# Example
start = datetime(2024, 1, 8)
result = add_business_days(start, 5)
print(result)  # 2024-01-15 (Monday)

推奨事項: 休日を含むより高度な営業日の計算には、python-dateutil ライブラリを使用します。

日付の書式設定

ISO 8601 フォーマット

from datetime import datetime

# Format as ISO 8601
dt = datetime(2024, 1, 8, 14, 30, 45)
iso_string = dt.isoformat()
print(iso_string)  # 2024-01-08T14:30:45

# With timezone (using pytz)
import pytz
tz = pytz.timezone('America/New_York')
dt = datetime(2024, 1, 8, 14, 30, 45, tzinfo=tz)
iso_with_tz = dt.isoformat()
print(iso_with_tz)  # 2024-01-08T14:30:45-05:00

strftime を使用したカスタム書式設定

from datetime import datetime

dt = datetime(2024, 1, 8, 14, 30, 45)

# Common format codes
formats = {
    'YYYY-MM-DD': dt.strftime('%Y-%m-%d'),  # 2024-01-08
    'YYYY/MM/DD HH:MM': dt.strftime('%Y/%m/%d %H:%M'),  # 2024/01/08 14:30
    'Day Month, Year': dt.strftime('%d %B, %Y'),  # 08 January, 2024
    'Weekday': dt.strftime('%A'),  # Monday
    'Short Weekday': dt.strftime('%a'),  # Mon
    'Time': dt.strftime('%H:%M:%S'),  # 14:30:45
    'AM/PM': dt.strftime('%I:%M %p'),  # 02:30 PM
}

for name, formatted in formats.items():
    print(f"{name}: {formatted}")

フォーマットコード:

> %Y  Year (4 digits)           %m  Month (01-12)
> %y  Year (2 digits)           %d  Day (01-31)
> %B  Month name (January)         %b  Month abbr (Jan)
> %A  Weekday name (Monday)       %a  Weekday abbr (Mon)
> %H  Hour (00-23)             %I  Hour (01-12)
> %M  Minute (00-59)            %S  Second (00-59)
> %p  AM/PM                     %f  Microseconds (000000-999999)
>

さまざまなロケールの形式

from datetime import datetime
import locale

dt = datetime(2024, 1, 8, 14, 30, 45)

# Set locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
en_format = dt.strftime('%B %d, %Y')  # January 08, 2024

locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8')
fr_format = dt.strftime('%d %B %Y')  # 08 janvier 2024

locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8')
zh_format = dt.strftime('%Y年%m月%d日')  # 2024年01月08日

注意: locale.setlocale() はプロセス全体に影響します。元のロケールを復元するには、locale.getlocale() を使用します。

日付の解析

ISO 8601 文字列の解析

from datetime import datetime

# Parse ISO 8601 string
iso_string = "2024-01-08T14:30:45"
dt = datetime.fromisoformat(iso_string)
print(dt)  # 2024-01-08 14:30:45

# Parse with timezone
iso_tz_string = "2024-01-08T14:30:45-05:00"
dt_tz = datetime.fromisoformat(iso_tz_string)
print(dt_tz)  # 2024-01-08 14:30:45-05:00

strptime を使用したカスタム形式の解析

from datetime import datetime

# Parse custom format
date_string = "08 January, 2024 14:30:45"
dt = datetime.strptime(date_string, '%d %B, %Y %H:%M:%S')
print(dt)  # 2024-01-08 14:30:45

# Parse US format
us_string = "01/08/2024 2:30 PM"
dt_us = datetime.strptime(us_string, '%m/%d/%Y %I:%M %p')
print(dt_us)  # 2024-01-08 14:30:00

# Parse 24-hour format
eu_string = "08.01.2024 14:30"
dt_eu = datetime.strptime(eu_string, '%d.%m.%Y %H:%M')
print(dt_eu)  # 2024-01-08 14:30:00

strptime のフォーマット コード:

> Same as strftime() format codes:
>   %Y (year), %m (month), %d (day)
>   %H (hour 24), %I (hour 12), %M (minute), %S (second)
>   %p (AM/PM), %f (microseconds)
>   %B (month name), %A (weekday name)
>

解析エラーの処理

from datetime import datetime

def safe_parse_date(date_string, format_string):
    """Parse date string with error handling"""
    try:
        return datetime.strptime(date_string, format_string)
    except ValueError as e:
        print(f"Failed to parse date: {date_string}")
        print(f"Error: {e}")
        return None

# Examples
valid = safe_parse_date("2024-01-08", "%Y-%m-%d")
invalid = safe_parse_date("invalid date", "%Y-%m-%d")

print(valid)   # 2024-01-08 00:00:00
print(invalid)  # Failed to parse date: invalid date

タイムゾーンの処理

pytz ライブラリの使用

from datetime import datetime
import pytz

# Create datetime with timezone
tz = pytz.timezone('America/New_York')
dt_aware = datetime(2024, 1, 8, 14, 30, 45, tzinfo=tz)
print(dt_aware)  # 2024-01-08 14:30:45-05:00

# Convert between timezones
tokyo_tz = pytz.timezone('Asia/Tokyo')
dt_tokyo = dt_aware.astimezone(tokyo_tz)
print(dt_tokyo)  # 2024-01-09 04:30:45+09:00

# Get current time in specific timezone
tz = pytz.timezone('Europe/London')
now_london = datetime.now(tz)
print(now_london)  # 2024-01-08 00:00:00+00:00

ベスト プラクティス: 包括的なタイムゾーンをサポートするには、pip install pytz を使用して pytz をインストールします。

ゾーン情報の使用 (Python 3.9 以降)

from datetime import datetime, timezone
from zoneinfo import ZoneInfo

# Python 3.9+ built-in timezone support
tz = ZoneInfo('America/New_York')
dt_aware = datetime(2024, 1, 8, 14, 30, 45, tzinfo=tz)
print(dt_aware)  # 2024-01-08 14:30:45-05:00

# Convert to UTC
dt_utc = dt_aware.astimezone(timezone.utc)
print(dt_utc)  # 2024-01-08 19:30:45+00:00

利点: zoneinfo は Python 3.9 以降に組み込まれているため、外部依存関係は必要ありません。

UTC と現地時間

from datetime import datetime

# Get local time (system timezone)
dt_local = datetime.now()
print(f"Local: {dt_local}")

# Get UTC time
dt_utc = datetime.utcnow()
print(f"UTC: {dt_utc}")

# Convert local to UTC (requires timezone-aware datetime)
import pytz
tz = pytz.timezone('America/New_York')
dt_aware = datetime.now(tz)
dt_utc = dt_aware.astimezone(pytz.utc)
print(f"Converted to UTC: {dt_utc}")

一般的な操作

期間の開始/終了

from datetime import datetime, timedelta

def start_of_day(dt):
    """Return start of day (midnight)"""
    return dt.replace(hour=0, minute=0, second=0, microsecond=0)

def end_of_day(dt):
    """Return end of day (23:59:59.999999)"""
    return dt.replace(hour=23, minute=59, second=59, microsecond=999999)

def start_of_month(dt):
    """Return start of month"""
    return dt.replace(day=1, hour=0, minute=0, second=0, microsecond=0)

def end_of_month(dt):
    """Return end of month"""
    if dt.month == 12:
        return dt.replace(year=dt.year + 1, month=1, day=1) - timedelta(days=1)
    return dt.replace(month=dt.month + 1, day=1) - timedelta(days=1)

# Examples
dt = datetime(2024, 1, 15, 14, 30, 45)
print(start_of_day(dt))    # 2024-01-15 00:00:00
print(end_of_month(dt))    # 2024-01-31 23:59:59.999999

年齢の計算

from datetime import datetime

def calculate_age(birth_date):
    """Calculate age in years, months, and days"""
    today = datetime.now()
    birth = datetime.fromisoformat(birth_date)

    years = today.year - birth.year
    months = today.month - birth.month
    days = today.day - birth.day

    # Adjust if birthday hasn't happened yet this year
    if (months < 0 or (months == 0 and days < 0)):
        years -= 1
        months += 12

    return {
        'years': years,
        'months': months,
        'days': days
    }

# Example
age = calculate_age('1990-06-15')
print(f"Age: {age['years']} years, {age['months']} months, {age['days']} days")
# Age: 33 years, 6 months, -7 days

カウントダウンタイマー

from datetime import datetime

def countdown(target_date_str):
    """Calculate countdown to target date"""
    target = datetime.fromisoformat(target_date_str)
    now = datetime.now()
    diff = target - now

    if diff.total_seconds() <= 0:
        return {'expired': True, 'text': 'Target date passed'}

    days = diff.days
    hours = diff.seconds // 3600
    minutes = (diff.seconds % 3600) // 60
    seconds = diff.seconds % 60

    return {
        'expired': False,
        'text': f"{days} days, {hours} hours, {minutes} minutes, {seconds} seconds",
        'total_seconds': diff.total_seconds()
    }

# Example
result = countdown('2024-12-31T00:00:00')
print(result['text'])
# "357 days, 11 hours, 29 minutes, 12 seconds"

ベストプラクティス

タイムゾーンのベスト プラクティス

✅ Always store UTC timestamps in databases
✅ Convert to local timezone only for display
✅ Use timezone-aware datetime objects for user-facing times
✅ Document timezone assumptions in code comments
✅ Use IANA timezone names (America/New_York, not UTC-5)
❌ Don't store local timestamps without timezone metadata
❌ Don't mix UTC and naive datetimes in calculations
❌ Don't assume server timezone matches user timezone
❌ Don't use pytz for Python 3.9+ (use zoneinfo instead)

パフォーマンスのヒント

✅ Use datetime.timestamp() instead of time.time() for datetime objects
✅ Cache timezone objects when used repeatedly
✅ Use datetime.utcnow() for UTC (faster than aware datetimes)
✅ Use timedelta arithmetic for time calculations (more readable)
❌ Don't create timezone objects in loops (reuse them)
❌ Don't call datetime.now() in tight loops (call once and reuse)

データの整合性

from datetime import datetime

def validate_datetime(dt):
    """Validate datetime object is within reasonable range"""
    if not isinstance(dt, datetime):
        return False, "Not a datetime object"

    if dt.year < 1900 or dt.year > 2100:
        return False, "Year out of reasonable range"

    if dt.month < 1 or dt.month > 12:
        return False, "Invalid month"

    if dt.day < 1 or dt.day > 31:
        return False, "Invalid day"

    return True, "Valid"

# Example
valid = validate_datetime(datetime(2024, 1, 8, 14, 30, 45))
print(valid)  # (True, "Valid")

invalid = validate_datetime(datetime(2024, 13, 1))
print(invalid)  # (False, "Invalid month")

関連ツール

追加リソース

複雑なタイムゾーンまたは営業日の要件がある運用アプリケーションの場合は、次の使用を検討してください。

  • pytz: レガシーだが広くサポートされているタイムゾーン ライブラリ
  • zoneinfo: 組み込み Python 3.9 以降 (新しいコードに推奨)
  • python-dateutil: 高度な日付解析と営業日の計算
  • 振り子: タイムゾーン処理が向上した Python の日時ライブラリ

Python の datetime モジュールは基本的な操作には十分ですが、ライブラリは複雑な使用例に対してより優れたタイムゾーンのサポートと解析を提供します。