Python datetime経過時間・時間差の計算方法【完全解説】

Pythonではdatetimeモジュールとtimeモジュールを使用して、経過時間や日時の差分を簡単に計算できます。この記事では、実用的なサンプルコードとともに詳しく解説します。

基本的な時間差の計算

datetimeオブジェクト同士の差分

from datetime import datetime, timedelta

# 2つの日時を設定
start = datetime(2024, 1, 15, 10, 30, 0)
end = datetime(2024, 1, 15, 14, 45, 30)

# 時間差を計算
diff = end - start
print(diff)                    # 4:15:30
print(type(diff))             # <class 'datetime.timedelta'>
print(f"差分: {diff.total_seconds()}秒")  # 差分: 15330.0秒

現在時刻との差分計算

from datetime import datetime

# 過去の時刻を設定
past_time = datetime(2024, 1, 1, 0, 0, 0)
now = datetime.now()

# 経過時間を計算
elapsed = now - past_time
print(f"経過日数: {elapsed.days}日")
print(f"経過時間: {elapsed.total_seconds()}秒")

実行時間の測定

基本的な実行時間測定

import time
from datetime import datetime

# 開始時刻を記録
start_time = datetime.now()

# 処理を実行(例:2秒待機)
time.sleep(2.5)

# 終了時刻を記録して差分計算
end_time = datetime.now()
execution_time = end_time - start_time

print(f"実行時間: {execution_time}")
print(f"実行時間(秒): {execution_time.total_seconds()}")

関数の実行時間を測定するデコレータ

from datetime import datetime
import functools

def measure_time(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = datetime.now()
        result = func(*args, **kwargs)
        end = datetime.now()
        elapsed = end - start
        print(f"{func.__name__}: {elapsed.total_seconds():.3f}秒")
        return result
    return wrapper

@measure_time
def sample_function():
    time.sleep(1)
    return "完了"

result = sample_function()  # sample_function: 1.001秒

timedeltaオブジェクトの詳細な扱い

timedeltaの各要素にアクセス

from datetime import datetime, timedelta

dt1 = datetime(2024, 1, 1, 10, 30, 25)
dt2 = datetime(2024, 1, 3, 14, 45, 50)

diff = dt2 - dt1
print(f"日数: {diff.days}")                    # 日数: 2
print(f"秒数: {diff.seconds}")                 # 秒数: 15325
print(f"マイクロ秒: {diff.microseconds}")      # マイクロ秒: 0
print(f"総秒数: {diff.total_seconds()}")       # 総秒数: 188725.0

時間差を時分秒で表示

def format_timedelta(td):
    total_seconds = int(td.total_seconds())
    days = total_seconds // 86400
    hours = (total_seconds % 86400) // 3600
    minutes = (total_seconds % 3600) // 60
    seconds = total_seconds % 60
    
    return f"{days}日 {hours}時間 {minutes}分 {seconds}秒"

diff = datetime(2024, 1, 3, 14, 45, 30) - datetime(2024, 1, 1, 10, 30, 25)
print(format_timedelta(diff))  # 2日 4時間 15分 5秒

高精度な時間測定

time.perf_counter()を使用

import time

# より高精度な時間測定
start = time.perf_counter()
time.sleep(0.1)
end = time.perf_counter()

print(f"実行時間: {end - start:.6f}秒")

コンテキストマネージャーで時間測定

import time
from contextlib import contextmanager

@contextmanager
def timer():
    start = time.perf_counter()
    yield
    end = time.perf_counter()
    print(f"実行時間: {end - start:.3f}秒")

# 使用例
with timer():
    time.sleep(0.5)
    # 何らかの処理

日付間の差分計算

年齢計算

from datetime import date

def calculate_age(birth_date, reference_date=None):
    if reference_date is None:
        reference_date = date.today()
    
    age = reference_date.year - birth_date.year
    if reference_date.month < birth_date.month or \
       (reference_date.month == birth_date.month and reference_date.day < birth_date.day):
        age -= 1
    
    return age

birth = date(1990, 3, 15)
age = calculate_age(birth)
print(f"年齢: {age}歳")

営業日の計算(土日を除く)

from datetime import datetime, timedelta

def count_business_days(start_date, end_date):
    count = 0
    current = start_date
    
    while current <= end_date:
        if current.weekday() < 5:  # 0-6 (月-日), 0-4が平日
            count += 1
        current += timedelta(days=1)
    
    return count

start = datetime(2024, 1, 15)  # 月曜日
end = datetime(2024, 1, 21)    # 日曜日

business_days = count_business_days(start, end)
print(f"営業日数: {business_days}日")  # 営業日数: 5日

時間差の比較と条件分岐

時間制限の実装

from datetime import datetime, timedelta

def is_within_time_limit(start_time, limit_minutes=30):
    now = datetime.now()
    elapsed = now - start_time
    limit = timedelta(minutes=limit_minutes)
    
    return elapsed <= limit

# 使用例
task_start = datetime.now()
# 何らかの処理...
time.sleep(1)

if is_within_time_limit(task_start, 60):
    print("制限時間内です")
else:
    print("制限時間を超えました")

時間帯による処理の分岐

from datetime import datetime, time

def get_time_period():
    now_time = datetime.now().time()
    
    if time(6, 0) <= now_time < time(12, 0):
        return "午前"
    elif time(12, 0) <= now_time < time(18, 0):
        return "午後"
    else:
        return "夜間"

period = get_time_period()
print(f"現在の時間帯: {period}")

まとめ

  • datetimeオブジェクト同士の演算でtimedeltaオブジェクトが得られる
  • total_seconds()で総秒数を取得可能
  • time.perf_counter()を使用すると高精度な測定が可能
  • 実用的な機能として、年齢計算や営業日計算も実装できる
  • コンテキストマネージャーやデコレータを活用すると便利

これらの方法を活用することで、Pythonでの時間計算処理が効率的に行えます。

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

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

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

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

■テックジム東京本校

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

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

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

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