プログラムを作っていると、「3日前の日付が知りたい」「2時間後の時刻を計算したい」「どのくらい時間が経ったか調べたい」といった場面がよく出てきます。
そんなときに便利なのが、Pythonのtimedelta(タイムデルタ)という機能です。これは時間の「差」や「長さ」を表すツールで、日付や時刻の計算を簡単にしてくれます。
この記事では、timedeltaを使って日付や時間を自由に計算する方法を、初心者の方にもわかりやすく説明します。
この記事で学べること
- timedeltaの基本的な使い方
- 日・時間・分・秒単位での計算方法
- 時間の差を比較する方法
- 実際のプロジェクトで使える応用テクニック
- よくある注意点とその対処法
timedeltaの基本的な使い方を覚えよう

timedeltaってなに?
timedeltaは、「時間の長さ」や「時間の差」を表すPythonの機能です。例えば:
- 1日という時間の長さ
- 3時間という時間の長さ
- 2つの日時の差
これらをプログラムで扱えるようにしたものがtimedeltaです。
最初の例:明日の日付を求める
まずは簡単な例から始めてみましょう:
from datetime import datetime, timedelta
# 現在の日時を取得
now = datetime.now()
print(f"今:{now}")
# 1日という時間の長さを作る
one_day = timedelta(days=1)
print(f"1日の長さ:{one_day}")
# 現在の時刻に1日を足す
tomorrow = now + one_day
print(f"明日:{tomorrow}")
実行結果の例
今:2024-06-01 14:25:30.123456
1日の長さ:1 day, 0:00:00
明日:2024-06-02 14:25:30.123456
コードの説明
timedelta(days=1)
:1日という時間の長さを作りますnow + one_day
:現在の時刻に1日を足し算します- 結果として、明日の同じ時刻が計算されます
過去の日付を求める(引き算)
足し算だけでなく、引き算もできます:
from datetime import datetime, timedelta
now = datetime.now()
# 1週間前の日付
last_week = now - timedelta(weeks=1)
print(f"1週間前:{last_week}")
# 3日前の日付
three_days_ago = now - timedelta(days=3)
print(f"3日前:{three_days_ago}")
# 昨日の日付
yesterday = now - timedelta(days=1)
print(f"昨日:{yesterday}")
実行結果の例
1週間前:2024-05-25 14:25:30.123456
3日前:2024-05-29 14:25:30.123456
昨日:2024-05-31 14:25:30.123456
timedeltaで指定できる時間の単位
timedeltaでは、様々な時間の単位を指定できます:
from datetime import timedelta
# 日数
days_delta = timedelta(days=7)
print(f"7日:{days_delta}")
# 週数
weeks_delta = timedelta(weeks=2)
print(f"2週間:{weeks_delta}")
# 時間
hours_delta = timedelta(hours=5)
print(f"5時間:{hours_delta}")
# 分
minutes_delta = timedelta(minutes=30)
print(f"30分:{minutes_delta}")
# 秒
seconds_delta = timedelta(seconds=45)
print(f"45秒:{seconds_delta}")
# 複数の単位を組み合わせ
complex_delta = timedelta(days=1, hours=2, minutes=30)
print(f"1日2時間30分:{complex_delta}")
実行結果の例
7日:7 days, 0:00:00
2週間:14 days, 0:00:00
5時間:5:00:00
30分:0:30:00
45秒:0:00:45
1日2時間30分:1 day, 2:30:00
実用的な例:期限の計算
実際のプロジェクトでよく使われる例をご紹介します:
from datetime import datetime, timedelta
def calculate_deadline(start_date, work_days):
"""作業開始日から締切日を計算する"""
deadline = start_date + timedelta(days=work_days)
return deadline
def time_until_deadline(deadline):
"""締切まであと何日かを計算する"""
now = datetime.now()
time_left = deadline - now
return time_left
# 使用例
project_start = datetime(2024, 6, 1, 9, 0, 0) # 6月1日 9時開始
deadline = calculate_deadline(project_start, 14) # 14日間のプロジェクト
print(f"プロジェクト開始:{project_start.strftime('%Y年%m月%d日 %H時%M分')}")
print(f"締切:{deadline.strftime('%Y年%m月%d日 %H時%M分')}")
remaining_time = time_until_deadline(deadline)
print(f"締切まで:{remaining_time}")
timedeltaを使えば、日付の足し算・引き算が直感的にできるようになります。次は、より細かい時間単位での操作を学びましょう。
時間・分・秒単位での細かい操作をマスターしよう

時間単位での計算
時間単位での計算も、timedeltaを使えば簡単です:
from datetime import datetime, timedelta
now = datetime.now()
print(f"現在時刻:{now.strftime('%Y年%m月%d日 %H時%M分%S秒')}")
# 3時間後
three_hours_later = now + timedelta(hours=3)
print(f"3時間後:{three_hours_later.strftime('%Y年%m月%d日 %H時%M分%S秒')}")
# 5時間前
five_hours_ago = now - timedelta(hours=5)
print(f"5時間前:{five_hours_ago.strftime('%Y年%m月%d日 %H時%M分%S秒')}")
# 12時間後(翌日になる場合もある)
twelve_hours_later = now + timedelta(hours=12)
print(f"12時間後:{twelve_hours_later.strftime('%Y年%m月%d日 %H時%M分%S秒')}")
実行結果の例
現在時刻:2024年06月01日 14時25分30秒
3時間後:2024年06月01日 17時25分30秒
5時間前:2024年06月01日 09時25分30秒
12時間後:2024年06月02日 02時25分30秒
分・秒単位での精密な計算
もっと細かい時間単位での計算も可能です:
from datetime import datetime, timedelta
now = datetime.now()
# 30分後
thirty_minutes_later = now + timedelta(minutes=30)
print(f"30分後:{thirty_minutes_later.strftime('%H時%M分')}")
# 45分前
forty_five_minutes_ago = now - timedelta(minutes=45)
print(f"45分前:{forty_five_minutes_ago.strftime('%H時%M分')}")
# 90秒後
ninety_seconds_later = now + timedelta(seconds=90)
print(f"90秒後:{ninety_seconds_later.strftime('%H時%M分%S秒')}")
# 複合的な時間計算
complex_time = now + timedelta(hours=1, minutes=15, seconds=30)
print(f"1時間15分30秒後:{complex_time.strftime('%H時%M分%S秒')}")
時間差を秒で取得する
2つの時刻の差を秒数で知りたい場合は、total_seconds()
メソッドを使います:
from datetime import datetime, timedelta
# 開始時刻と終了時刻を設定
start_time = datetime(2024, 6, 1, 12, 0, 0) # 12:00:00
end_time = datetime(2024, 6, 1, 14, 30, 45) # 14:30:45
# 時間差を計算
time_diff = end_time - start_time
print(f"時間差:{time_diff}")
# 秒数で取得
total_seconds = time_diff.total_seconds()
print(f"総秒数:{total_seconds}秒")
# 分数で表示
total_minutes = total_seconds / 60
print(f"総分数:{total_minutes}分")
# 時間数で表示
total_hours = total_seconds / 3600
print(f"総時間数:{total_hours}時間")
実行結果の例
時間差:2:30:45
総秒数:9045.0秒
総分数:150.75分
総時間数:2.5125時間
実用例:処理時間の測定
プログラムの実行時間を測定する例:
from datetime import datetime, timedelta
import time
def measure_processing_time():
"""処理時間を測定する例"""
print("処理を開始します...")
start_time = datetime.now()
# 何らかの処理をシミュレーション(3秒待機)
time.sleep(3)
end_time = datetime.now()
processing_time = end_time - start_time
print(f"処理が完了しました")
print(f"開始時刻:{start_time.strftime('%H時%M分%S秒')}")
print(f"終了時刻:{end_time.strftime('%H時%M分%S秒')}")
print(f"処理時間:{processing_time}")
print(f"処理時間(秒):{processing_time.total_seconds()}秒")
# 関数を実行
measure_processing_time()
営業時間の計算
ビジネスシステムでよく使われる営業時間の計算例:
from datetime import datetime, timedelta
class BusinessHours:
"""営業時間を管理するクラス"""
def __init__(self, open_hour=9, close_hour=18):
self.open_hour = open_hour # 営業開始時刻
self.close_hour = close_hour # 営業終了時刻
def get_business_hours_today(self):
"""今日の営業時間を取得"""
today = datetime.now().date()
# 営業開始時刻
open_time = datetime.combine(today, datetime.min.time()) + timedelta(hours=self.open_hour)
# 営業終了時刻
close_time = datetime.combine(today, datetime.min.time()) + timedelta(hours=self.close_hour)
return open_time, close_time
def is_business_hours(self, check_time=None):
"""指定時刻が営業時間内かチェック"""
if check_time is None:
check_time = datetime.now()
open_time, close_time = self.get_business_hours_today()
return open_time <= check_time <= close_time
def time_until_open(self):
"""営業開始まであと何時間か"""
now = datetime.now()
open_time, _ = self.get_business_hours_today()
if now < open_time:
return open_time - now
else:
# 明日の営業開始時刻
tomorrow_open = open_time + timedelta(days=1)
return tomorrow_open - now
def time_until_close(self):
"""営業終了まであと何時間か"""
now = datetime.now()
_, close_time = self.get_business_hours_today()
if now < close_time:
return close_time - now
else:
return timedelta(0) # すでに営業終了
# 使用例
business = BusinessHours(9, 18) # 9時〜18時営業
print("営業時間チェック:")
print(f"現在営業中?:{business.is_business_hours()}")
time_to_open = business.time_until_open()
time_to_close = business.time_until_close()
print(f"営業開始まで:{time_to_open}")
print(f"営業終了まで:{time_to_close}")
時間・分・秒単位での計算も、timedeltaがあれば簡単に実現できます。精密な時間管理が必要なシステムでも活用できます。
timedeltaの比較・条件分岐を活用しよう
時間差の比較
timedeltaは、大小比較ができるので条件分岐で使えます:
from datetime import datetime, timedelta
# 2つの時刻を設定
start_time = datetime(2024, 6, 1, 10, 0, 0)
end_time = datetime(2024, 6, 1, 12, 30, 0)
# 時間差を計算
time_diff = end_time - start_time
print(f"時間差:{time_diff}")
# 1時間より長いかチェック
if time_diff > timedelta(hours=1):
print("1時間以上の差があります")
else:
print("1時間未満の差です")
# 2時間より短いかチェック
if time_diff < timedelta(hours=2):
print("2時間未満の差です")
# 3時間と同じかチェック
if time_diff == timedelta(hours=2, minutes=30):
print("ちょうど2時間30分の差です")
実行結果の例
時間差:2:30:00
1時間以上の差があります
2時間未満の差です
ちょうど2時間30分の差です
経過時間をチェックする実用例
プログラムの実行状況を監視する例:
from datetime import datetime, timedelta
import time
def monitor_process():
"""プロセスの実行時間を監視する"""
start_time = datetime.now()
print(f"処理開始:{start_time.strftime('%H時%M分%S秒')}")
# 長時間かかる処理をシミュレーション
for i in range(10):
time.sleep(0.5) # 0.5秒待機
# 経過時間をチェック
elapsed = datetime.now() - start_time
print(f"ステップ {i+1}: 経過時間 {elapsed}")
# 5秒経過したら警告
if elapsed > timedelta(seconds=5):
print("⚠️ 処理に時間がかかりすぎています")
break
total_time = datetime.now() - start_time
print(f"処理完了:総実行時間 {total_time}")
# 実行
monitor_process()
ファイルの更新チェック
ファイルが最近更新されたかをチェックする例:
from datetime import datetime, timedelta
import os
def check_file_freshness(filepath, max_age_hours=24):
"""ファイルが指定時間以内に更新されているかチェック"""
try:
# ファイルの最終更新時刻を取得
file_time = datetime.fromtimestamp(os.path.getmtime(filepath))
current_time = datetime.now()
# 経過時間を計算
age = current_time - file_time
max_age = timedelta(hours=max_age_hours)
print(f"ファイル:{filepath}")
print(f"最終更新:{file_time.strftime('%Y年%m月%d日 %H時%M分')}")
print(f"経過時間:{age}")
if age < max_age:
print(f"✅ ファイルは新しいです({max_age_hours}時間以内)")
return True
else:
print(f"⚠️ ファイルが古くなっています({max_age_hours}時間以上経過)")
return False
except FileNotFoundError:
print(f"❌ ファイルが見つかりません:{filepath}")
return False
# 使用例(実際のファイルパスに変更してください)
is_fresh = check_file_freshness("example.txt", 6) # 6時間以内かチェック
タスクスケジューラの例
定期的にタスクを実行するスケジューラの例:
from datetime import datetime, timedelta
class TaskScheduler:
"""簡単なタスクスケジューラ"""
def __init__(self):
self.last_daily_task = None
self.last_hourly_task = None
self.last_weekly_task = None
def should_run_daily_task(self):
"""日次タスクを実行すべきかチェック"""
now = datetime.now()
if self.last_daily_task is None:
return True
elapsed = now - self.last_daily_task
return elapsed >= timedelta(days=1)
def should_run_hourly_task(self):
"""時間次タスクを実行すべきかチェック"""
now = datetime.now()
if self.last_hourly_task is None:
return True
elapsed = now - self.last_hourly_task
return elapsed >= timedelta(hours=1)
def should_run_weekly_task(self):
"""週次タスクを実行すべきかチェック"""
now = datetime.now()
if self.last_weekly_task is None:
return True
elapsed = now - self.last_weekly_task
return elapsed >= timedelta(weeks=1)
def run_daily_task(self):
"""日次タスクを実行"""
print("📅 日次タスクを実行中...")
self.last_daily_task = datetime.now()
print(f"次回実行予定:{(self.last_daily_task + timedelta(days=1)).strftime('%m月%d日 %H時%M分')}")
def run_hourly_task(self):
"""時間次タスクを実行"""
print("⏰ 時間次タスクを実行中...")
self.last_hourly_task = datetime.now()
print(f"次回実行予定:{(self.last_hourly_task + timedelta(hours=1)).strftime('%H時%M分')}")
def run_weekly_task(self):
"""週次タスクを実行"""
print("📆 週次タスクを実行中...")
self.last_weekly_task = datetime.now()
print(f"次回実行予定:{(self.last_weekly_task + timedelta(weeks=1)).strftime('%m月%d日')}")
def check_and_run_tasks(self):
"""すべてのタスクをチェックして必要に応じて実行"""
print(f"タスクチェック開始:{datetime.now().strftime('%Y年%m月%d日 %H時%M分')}")
if self.should_run_weekly_task():
self.run_weekly_task()
if self.should_run_daily_task():
self.run_daily_task()
if self.should_run_hourly_task():
self.run_hourly_task()
print("タスクチェック完了\n")
# 使用例
scheduler = TaskScheduler()
scheduler.check_and_run_tasks()
# 1時間1分後のシミュレーション
scheduler.last_hourly_task = datetime.now() - timedelta(hours=1, minutes=1)
scheduler.check_and_run_tasks()
セッション管理の例
ユーザーセッションの有効期限をチェックする例:
from datetime import datetime, timedelta
class UserSession:
"""ユーザーセッション管理"""
def __init__(self, user_id, session_duration_hours=2):
self.user_id = user_id
self.login_time = datetime.now()
self.last_activity = datetime.now()
self.session_duration = timedelta(hours=session_duration_hours)
def update_activity(self):
"""最終活動時刻を更新"""
self.last_activity = datetime.now()
print(f"ユーザー {self.user_id} の活動を記録しました")
def is_session_valid(self):
"""セッションが有効かチェック"""
now = datetime.now()
elapsed = now - self.last_activity
return elapsed < self.session_duration
def time_until_expiry(self):
"""セッション期限切れまでの時間"""
now = datetime.now()
expiry_time = self.last_activity + self.session_duration
if now < expiry_time:
return expiry_time - now
else:
return timedelta(0)
def get_session_info(self):
"""セッション情報を表示"""
print(f"ユーザーID:{self.user_id}")
print(f"ログイン時刻:{self.login_time.strftime('%H時%M分')}")
print(f"最終活動:{self.last_activity.strftime('%H時%M分')}")
print(f"セッション有効:{self.is_session_valid()}")
if self.is_session_valid():
remaining = self.time_until_expiry()
hours = remaining.total_seconds() // 3600
minutes = (remaining.total_seconds() % 3600) // 60
print(f"残り時間:{int(hours)}時間{int(minutes)}分")
else:
print("セッション期限切れ")
# 使用例
user_session = UserSession("user123", 1) # 1時間のセッション
user_session.get_session_info()
print("\n--- 30分後の活動 ---")
user_session.last_activity = datetime.now() - timedelta(minutes=30)
user_session.update_activity()
user_session.get_session_info()
timedeltaの比較機能を使うことで、時間ベースの条件判定を簡単に実装できます。これにより、より柔軟で実用的なプログラムが作れるようになります。
注意点と応用テクニックを理解しよう
timedeltaの重要な注意点
年や月の単位はサポートされていない
timedeltaで一番注意すべき点は、年や月の単位が使えないことです:
from datetime import timedelta
# ❌ これらはエラーになります
# wrong1 = timedelta(years=1) # TypeError
# wrong2 = timedelta(months=3) # TypeError
# ✅ 使える単位
correct = timedelta(
weeks=2, # 週
days=5, # 日
hours=3, # 時間
minutes=30, # 分
seconds=45, # 秒
microseconds=123456 # マイクロ秒
)
print(f"正しいtimedelta:{correct}")
なぜ年や月が使えないの?
年や月は日数が一定ではないからです:
- 月:28日〜31日(月によって異なる)
- 年:365日または366日(うるう年によって異なる)
年月の計算が必要な場合の対処法
年や月の計算が必要な場合は、dateutil
ライブラリを使うか、手動で計算します:
from datetime import datetime, timedelta
def add_months(start_date, months):
"""月を加算する関数(手動実装)"""
year = start_date.year
month = start_date.month + months
# 年の調整
while month > 12:
year += 1
month -= 12
while month < 1:
year -= 1
month += 12
# 日付の調整(月末の場合)
try:
return start_date.replace(year=year, month=month)
except ValueError:
# 例:1月31日から1ヶ月後は2月28日(または29日)
from calendar import monthrange
last_day = monthrange(year, month)[1]
return start_date.replace(year=year, month=month, day=last_day)
# 使用例
start = datetime(2024, 1, 31)
print(f"開始日:{start.strftime('%Y年%m月%d日')}")
one_month_later = add_months(start, 1)
print(f"1ヶ月後:{one_month_later.strftime('%Y年%m月%d日')}")
six_months_later = add_months(start, 6)
print(f"6ヶ月後:{six_months_later.strftime('%Y年%m月%d日')}")
負の値も使える
timedeltaでは負の値も使えます:
from datetime import datetime, timedelta
now = datetime.now()
# 負の値を使った計算
past_time = now + timedelta(days=-7) # 7日前
future_time = now + timedelta(hours=-3) # 3時間前
print(f"現在:{now.strftime('%Y年%m月%d日 %H時%M分')}")
print(f"7日前:{past_time.strftime('%Y年%m月%d日 %H時%M分')}")
print(f"3時間前:{future_time.strftime('%Y年%m月%d日 %H時%M分')}")
# 引き算と同じ結果
same_result1 = now - timedelta(days=7)
same_result2 = now + timedelta(days=-7)
print(f"引き算:{same_result1}")
print(f"負の値:{same_result2}")
print(f"同じ結果?:{same_result1 == same_result2}")
繰り返し処理での活用
一定期間ごとの繰り返し処理は、timedeltaの得意分野です:
from datetime import datetime, timedelta
def generate_date_range(start_date, end_date, step_days=1):
"""指定期間の日付リストを生成する"""
dates = []
current_date = start_date
while current_date <= end_date:
dates.append(current_date)
current_date += timedelta(days=step_days)
return dates
def print_weekly_schedule(start_date, weeks=4):
"""週次スケジュールを表示する"""
print(f"週次スケジュール({weeks}週間):")
for week in range(weeks):
week_start = start_date + timedelta(weeks=week)
week_end = week_start + timedelta(days=6)
print(f"第{week + 1}週:{week_start.strftime('%m月%d日')} 〜 {week_end.strftime('%m月%d日')}")
def create_backup_schedule():
"""バックアップスケジュールを作成する"""
print("バックアップスケジュール:")
base_time = datetime(2024, 6, 1, 2, 0, 0) # 深夜2時
# 毎日のバックアップ(1週間分)
print("日次バックアップ:")
for day in range(7):
backup_time = base_time + timedelta(days=day)
print(f" {backup_time.strftime('%m月%d日 %H時%M分')}")
print("\n週次バックアップ:")
for week in range(4):
weekly_backup = base_time + timedelta(weeks=week)
print(f" {weekly_backup.strftime('%m月%d日 %H時%M分')}")
# 使用例
start = datetime(2024, 6, 1)
end = datetime(2024, 6, 10)
print("期間内の全日付:")
date_list = generate_date_range(start, end)
for date in date_list:
print(f" {date.strftime('%Y年%m月%d日 (%a)')}")
print("\n" + "="*40)
print_weekly_schedule(start, 3)
print("\n" + "="*40)
create_backup_schedule()
実用的な応用例:ログローテーション
ログファイルを定期的に切り替える仕組み:
from datetime import datetime, timedelta
import os
class LogRotator:
"""ログファイルのローテーション管理"""
def __init__(self, log_dir="logs", keep_days=30):
self.log_dir = log_dir
self.keep_days = keep_days
def get_today_log_filename(self):
"""今日のログファイル名を取得"""
today = datetime.now()
filename = f"app_{today.strftime('%Y%m%d')}.log"
return os.path.join(self.log_dir, filename)
def get_hourly_log_filename(self):
"""時間別ログファイル名を取得"""
now = datetime.now()
filename = f"app_{now.strftime('%Y%m%d_%H')}.log"
return os.path.join(self.log_dir, filename)
def should_rotate_daily(self, last_rotation):
"""日次ローテーションが必要かチェック"""
if last_rotation is None:
return True
now = datetime.now()
elapsed = now - last_rotation
return elapsed >= timedelta(days=1)
def should_rotate_hourly(self, last_rotation):
"""時間次ローテーションが必要かチェック"""
if last_rotation is None:
return True
now = datetime.now()
elapsed = now - last_rotation
return elapsed >= timedelta(hours=1)
def cleanup_old_logs(self):
"""古いログファイルを削除"""
if not os.path.exists(self.log_dir):
return
cutoff_date = datetime.now() - timedelta(days=self.keep_days)
deleted_count = 0
for filename in os.listdir(self.log_dir):
if filename.startswith("app_") and filename.endswith(".log"):
filepath = os.path.join(self.log_dir, filename)
try:
file_time = datetime.fromtimestamp(os.path.getmtime(filepath))
if file_time < cutoff_date:
os.remove(filepath)
deleted_count += 1
print(f"削除:{filename}")
except OSError:
continue
print(f"合計 {deleted_count} 個の古いログファイルを削除しました")
# 使用例
rotator = LogRotator()
print(f"今日のログファイル:{rotator.get_today_log_filename()}")
print(f"現在の時間別ログファイル:{rotator.get_hourly_log_filename()}")
パフォーマンス測定ツール
処理時間を詳細に測定するツール:
from datetime import datetime, timedelta
import time
class PerformanceTimer:
"""パフォーマンス測定ツール"""
def __init__(self):
self.start_time = None
self.end_time = None
self.checkpoints = []
def start(self):
"""測定開始"""
self.start_time = datetime.now()
self.checkpoints = []
print(f"⏱️ 測定開始:{self.start_time.strftime('%H時%M分%S秒')}")
def checkpoint(self, description=""):
"""チェックポイントを記録"""
if self.start_time is None:
print("❌ 測定が開始されていません")
return
checkpoint_time = datetime.now()
elapsed = checkpoint_time - self.start_time
self.checkpoints.append({
'time': checkpoint_time,
'elapsed': elapsed,
'description': description
})
print(f"📍 {description}: {elapsed}")
def stop(self):
"""測定終了"""
if self.start_time is None:
print("❌ 測定が開始されていません")
return
self.end_time = datetime.now()
total_time = self.end_time - self.start_time
print(f"🏁 測定終了:{self.end_time.strftime('%H時%M分%S秒')}")
print(f"📊 総実行時間:{total_time}")
return total_time
def report(self):
"""詳細レポートを表示"""
if not self.checkpoints:
print("チェックポイントがありません")
return
print("\n" + "="*50)
print("📈 パフォーマンスレポート")
print("="*50)
prev_time = self.start_time
for i, checkpoint in enumerate(self.checkpoints):
step_time = checkpoint['time'] - prev_time
total_elapsed = checkpoint['elapsed']
print(f"ステップ {i+1}: {checkpoint['description']}")
print(f" ステップ時間: {step_time}")
print(f" 累積時間: {total_elapsed}")
print()
prev_time = checkpoint['time']
if self.end_time:
final_step = self.end_time - prev_time
total_time = self.end_time - self.start_time
print(f"最終処理時間: {final_step}")
print(f"総実行時間: {total_time}")
# 使用例
def example_long_process():
"""時間のかかる処理のシミュレーション"""
timer = PerformanceTimer()
timer.start()
# 初期化処理
time.sleep(0.5)
timer.checkpoint("初期化処理完了")
# データ読み込み
time.sleep(1.0)
timer.checkpoint("データ読み込み完了")
# データ処理
time.sleep(1.5)
timer.checkpoint("データ処理完了")
# 結果保存
time.sleep(0.8)
timer.checkpoint("結果保存完了")
total_time = timer.stop()
timer.report()
# 推奨実行時間との比較
recommended_time = timedelta(seconds=3)
if total_time > recommended_time:
print(f"⚠️ 処理時間が推奨時間({recommended_time})を超えています")
else:
print(f"✅ 処理時間は推奨範囲内です")
# 実行
example_long_process()
イベントスケジューリングシステム
イベントの管理とスケジューリング:
from datetime import datetime, timedelta
class Event:
"""イベントクラス"""
def __init__(self, name, start_time, duration_minutes=60):
self.name = name
self.start_time = start_time
self.duration = timedelta(minutes=duration_minutes)
self.end_time = start_time + self.duration
def __str__(self):
return f"{self.name} ({self.start_time.strftime('%m/%d %H:%M')} - {self.end_time.strftime('%H:%M')})"
class EventScheduler:
"""イベントスケジューラー"""
def __init__(self):
self.events = []
def add_event(self, event):
"""イベントを追加"""
self.events.append(event)
self.events.sort(key=lambda e: e.start_time)
def get_events_today(self):
"""今日のイベントを取得"""
today = datetime.now().date()
today_events = []
for event in self.events:
if event.start_time.date() == today:
today_events.append(event)
return today_events
def get_upcoming_events(self, hours=24):
"""指定時間内の今後のイベントを取得"""
now = datetime.now()
cutoff_time = now + timedelta(hours=hours)
upcoming = []
for event in self.events:
if now <= event.start_time <= cutoff_time:
upcoming.append(event)
return upcoming
def check_conflicts(self, new_event):
"""スケジュール競合をチェック"""
conflicts = []
for event in self.events:
# 時間の重複をチェック
if (new_event.start_time < event.end_time and
new_event.end_time > event.start_time):
conflicts.append(event)
return conflicts
def get_free_time_today(self):
"""今日の空き時間を計算"""
today = datetime.now().date()
today_events = self.get_events_today()
if not today_events:
return "終日空いています"
# 営業時間を9:00-18:00と仮定
business_start = datetime.combine(today, datetime.min.time()) + timedelta(hours=9)
business_end = datetime.combine(today, datetime.min.time()) + timedelta(hours=18)
free_periods = []
current_time = business_start
for event in today_events:
if current_time < event.start_time:
duration = event.start_time - current_time
if duration >= timedelta(minutes=30): # 30分以上の空きのみ
free_periods.append(f"{current_time.strftime('%H:%M')}-{event.start_time.strftime('%H:%M')}")
current_time = max(current_time, event.end_time)
# 最後のイベント後の空き時間
if current_time < business_end:
duration = business_end - current_time
if duration >= timedelta(minutes=30):
free_periods.append(f"{current_time.strftime('%H:%M')}-{business_end.strftime('%H:%M')}")
return free_periods if free_periods else "空き時間がありません"
def print_schedule(self, days=1):
"""スケジュールを表示"""
start_date = datetime.now().date()
for day in range(days):
target_date = start_date + timedelta(days=day)
day_events = [e for e in self.events if e.start_time.date() == target_date]
print(f"\n📅 {target_date.strftime('%Y年%m月%d日')} のスケジュール:")
if not day_events:
print(" 予定はありません")
continue
for event in day_events:
duration_hours = event.duration.total_seconds() / 3600
print(f" 🕐 {event} (時間: {duration_hours:.1f}時間)")
# 使用例
scheduler = EventScheduler()
# イベントを追加
base_date = datetime.now().replace(hour=10, minute=0, second=0, microsecond=0)
events = [
Event("チームミーティング", base_date, 60),
Event("プレゼンテーション", base_date + timedelta(hours=2), 90),
Event("クライアント打ち合わせ", base_date + timedelta(hours=5), 120),
Event("明日の企画会議", base_date + timedelta(days=1), 90)
]
for event in events:
conflicts = scheduler.check_conflicts(event)
if conflicts:
print(f"⚠️ 競合が見つかりました:{event.name}")
for conflict in conflicts:
print(f" 競合イベント:{conflict}")
else:
scheduler.add_event(event)
print(f"✅ イベントを追加:{event}")
print("\n" + "="*50)
scheduler.print_schedule(2)
print(f"\n今後24時間のイベント:")
upcoming = scheduler.get_upcoming_events(24)
for event in upcoming:
time_until = event.start_time - datetime.now()
hours = time_until.total_seconds() / 3600
print(f" {event} (あと {hours:.1f}時間)")
print(f"\n今日の空き時間:")
free_time = scheduler.get_free_time_today()
if isinstance(free_time, list):
for period in free_time:
print(f" 🕐 {period}")
else:
print(f" {free_time}")
timedeltaの算術演算
timedeltaは算術演算も可能です:
from datetime import timedelta
# timedeltaの足し算
duration1 = timedelta(hours=2, minutes=30)
duration2 = timedelta(hours=1, minutes=45)
total_duration = duration1 + duration2
print(f"時間1:{duration1}")
print(f"時間2:{duration2}")
print(f"合計:{total_duration}")
# timedeltaの引き算
difference = duration1 - duration2
print(f"差:{difference}")
# timedeltaの掛け算
doubled = duration1 * 2
print(f"2倍:{doubled}")
# timedeltaの割り算
half = duration1 / 2
print(f"半分:{half}")
# 比率の計算
ratio = duration1 / duration2
print(f"比率:{ratio:.2f}")
# 絶対値
negative_duration = timedelta(hours=-3)
absolute_duration = abs(negative_duration)
print(f"負の値:{negative_duration}")
print(f"絶対値:{absolute_duration}")
まとめ
Pythonのtimedelta
は、日付や時間の計算を直感的で簡単にしてくれる非常に便利なツールです。
timedeltaの主な特徴
- 簡単な日時計算:足し算・引き算で直感的に操作
- 柔軟な時間単位:日・時間・分・秒・マイクロ秒に対応
- 比較演算対応:条件分岐で時間ベースの判定が可能
- 算術演算対応:掛け算・割り算で時間の計算が可能
実用的な活用場面
- ログ分析:一定期間のデータフィルタリング
- スケジュール管理:イベントの時間計算と競合チェック
- パフォーマンス測定:処理時間の測定と分析
- 定期処理:バックアップやメンテナンスのスケジューリング
- セッション管理:ログイン状態の有効期限チェック
注意すべきポイント
- 年や月の単位は直接サポートされていない
- 必要に応じて手動実装や外部ライブラリを使用
- タイムゾーンは別途考慮が必要
コメント