todoapp-vgv7cg/app/utils/date_utils.py
Automated Action 66410bdab5 Implement comprehensive due date functionality for todos
Added due_date field to TodoBase, TodoCreate, TodoUpdate schemas with proper validation
and timezone handling. Included computed fields is_overdue and days_until_due
for enhanced todo management capabilities.
2025-06-19 13:20:33 +00:00

78 lines
2.9 KiB
Python

"""Date utility functions for todo management."""
from datetime import datetime, timezone, timedelta
from typing import Tuple, Optional
def get_timezone_aware_now() -> datetime:
"""Get current time in UTC timezone."""
return datetime.now(timezone.utc)
def get_date_range_today() -> Tuple[datetime, datetime]:
"""Get start and end of today in UTC."""
now = get_timezone_aware_now()
start_of_day = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_of_day = now.replace(hour=23, minute=59, second=59, microsecond=999999)
return start_of_day, end_of_day
def get_date_range_this_week() -> Tuple[datetime, datetime]:
"""Get start and end of current week (Monday to Sunday) in UTC."""
now = get_timezone_aware_now()
start_of_week = now - timedelta(days=now.weekday())
start_of_week = start_of_week.replace(hour=0, minute=0, second=0, microsecond=0)
end_of_week = start_of_week + timedelta(days=6, hours=23, minutes=59, seconds=59, microseconds=999999)
return start_of_week, end_of_week
def get_date_range_next_week() -> Tuple[datetime, datetime]:
"""Get start and end of next week (Monday to Sunday) in UTC."""
now = get_timezone_aware_now()
days_until_next_monday = 7 - now.weekday()
start_of_next_week = now + timedelta(days=days_until_next_monday)
start_of_next_week = start_of_next_week.replace(hour=0, minute=0, second=0, microsecond=0)
end_of_next_week = start_of_next_week + timedelta(days=6, hours=23, minutes=59, seconds=59, microseconds=999999)
return start_of_next_week, end_of_next_week
def get_date_range_next_days(days: int) -> Tuple[datetime, datetime]:
"""Get start and end of next N days in UTC."""
now = get_timezone_aware_now()
start_time = now
end_time = now + timedelta(days=days)
return start_time, end_time
def get_overdue_cutoff() -> datetime:
"""Get cutoff datetime for overdue todos (current time)."""
return get_timezone_aware_now()
def get_due_soon_cutoff(days: int = 7) -> datetime:
"""Get cutoff datetime for due soon todos (next N days)."""
return get_timezone_aware_now() + timedelta(days=days)
def is_overdue(due_date: Optional[datetime], completed: bool = False) -> bool:
"""Check if a todo is overdue."""
if due_date is None or completed:
return False
return get_timezone_aware_now() > due_date
def is_due_today(due_date: Optional[datetime]) -> bool:
"""Check if a todo is due today."""
if due_date is None:
return False
today_start, today_end = get_date_range_today()
return today_start <= due_date <= today_end
def is_due_soon(due_date: Optional[datetime], days: int = 7, completed: bool = False) -> bool:
"""Check if a todo is due within the next N days."""
if due_date is None or completed:
return False
cutoff = get_due_soon_cutoff(days)
now = get_timezone_aware_now()
return now <= due_date <= cutoff