fix: convert calendar event times to user timezone in briefing

The briefing was formatting event start_dt directly in UTC instead of
converting to the user's local timezone. Also, the day_start/day_end
query window was naive (UTC), so events at the edges of the user's day
could be missed or included incorrectly.

Now reads user_timezone setting, uses it for today's date boundary and
for converting each event's start_dt before formatting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 06:34:22 -04:00
parent aab478359b
commit 383a4430f1
@@ -8,6 +8,7 @@ import asyncio
import hashlib
import logging
from datetime import date, datetime, timezone
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
import httpx
@@ -129,7 +130,13 @@ async def _gather_internal(user_id: int) -> dict:
from fabledassistant.services.projects import list_projects
from fabledassistant.services.caldav import is_caldav_configured, list_events
today = date.today().isoformat()
tz_name = await get_setting(user_id, "user_timezone") or "UTC"
try:
user_tz = ZoneInfo(tz_name)
except ZoneInfoNotFoundError:
user_tz = ZoneInfo("UTC")
today = datetime.now(user_tz).date().isoformat()
# Tasks: overdue, due today, high priority in-progress
all_tasks: list[dict] = []
@@ -166,9 +173,9 @@ async def _gather_internal(user_id: int) -> dict:
calendar_events: list[str] = []
try:
from fabledassistant.services.events import list_events as list_internal_events
today_date = date.today()
day_start = datetime(today_date.year, today_date.month, today_date.day, 0, 0, 0)
day_end = datetime(today_date.year, today_date.month, today_date.day, 23, 59, 59)
today_date = datetime.now(user_tz).date()
day_start = datetime(today_date.year, today_date.month, today_date.day, 0, 0, 0, tzinfo=user_tz)
day_end = datetime(today_date.year, today_date.month, today_date.day, 23, 59, 59, tzinfo=user_tz)
internal_events = await list_internal_events(
user_id=user_id, date_from=day_start, date_to=day_end
)
@@ -176,7 +183,8 @@ async def _gather_internal(user_id: int) -> dict:
if e.all_day:
time_str = "all day"
elif e.start_dt:
time_str = e.start_dt.strftime("%-I:%M %p")
local_dt = e.start_dt.astimezone(user_tz) if e.start_dt.tzinfo else e.start_dt.replace(tzinfo=timezone.utc).astimezone(user_tz)
time_str = local_dt.strftime("%-I:%M %p")
else:
time_str = "unknown time"
calendar_events.append(f"{e.title} at {time_str}")