todoapp-vgv7cg/app/utils/date_utils.py
Automated Action 2519513d99 Implement comprehensive due date CRUD operations and filtering
- Add enhanced due date filtering to get_todos function with support for "today", "this_week", "next_week"
- Add overdue filtering parameter with timezone-aware comparisons
- Add sorting by due_date with null values at end
- Add get_overdue_todos function for retrieving overdue todos
- Add get_todos_due_soon function for todos due within next N days (default 7)
- Add get_todos_by_date_range function for custom date range filtering
- Create comprehensive date utilities in app/utils/date_utils.py with timezone support
- Add project_id and tag_ids support to TodoCreate and TodoUpdate schemas
- Include efficient database indexing for due_date queries
- Use SQLAlchemy timezone-aware datetime filtering throughout
- Add proper overdue detection logic with timezone handling
2025-06-19 13:20:58 +00:00

87 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