[verified] feat: support monthly completion recurrence
This commit is contained in:
@@ -2,6 +2,7 @@ from datetime import UTC, datetime, time, timedelta
|
||||
from uuid import UUID
|
||||
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -25,10 +26,15 @@ def _user_zone(user: User) -> ZoneInfo:
|
||||
raise HTTPException(422, "用户时区无效") from exc
|
||||
|
||||
|
||||
def _after_completion_due(task: Task, completed_at: datetime, days: int, user: User) -> datetime:
|
||||
def _after_completion_due(
|
||||
task: Task, completed_at: datetime, value: int, unit: str | None, user: User
|
||||
) -> datetime:
|
||||
zone = _user_zone(user)
|
||||
completed_local = completed_at.astimezone(zone)
|
||||
target_date = completed_local.date() + timedelta(days=days)
|
||||
if unit == "months":
|
||||
target_date = completed_local.date() + relativedelta(months=value)
|
||||
else:
|
||||
target_date = completed_local.date() + timedelta(days=value)
|
||||
if task.due_has_time:
|
||||
due_local = task.due_at.astimezone(zone)
|
||||
wall_time = due_local.timetz().replace(tzinfo=None)
|
||||
@@ -67,7 +73,11 @@ async def apply_task_changes(
|
||||
if recurrence.trigger_mode == "after_completion":
|
||||
completed_at = utcnow()
|
||||
next_due = _after_completion_due(
|
||||
task, completed_at, recurrence.after_completion_days, user
|
||||
task,
|
||||
completed_at,
|
||||
recurrence.after_completion_days,
|
||||
recurrence.after_completion_unit,
|
||||
user,
|
||||
)
|
||||
changes["completed"] = False
|
||||
changes["due_at"] = next_due
|
||||
|
||||
Reference in New Issue
Block a user