Display calendar events in local timezone (PST)
- Query using local "today/tomorrow/week" boundaries converted to UTC - Display event times converted to America/Los_Angeles timezone - Headers show local dates (Dec 31, 2025 instead of Jan 1, 2026) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,10 @@ import argparse
|
||||
import subprocess
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
# Local timezone for display
|
||||
LOCAL_TZ = ZoneInfo('America/Los_Angeles')
|
||||
|
||||
# OAuth setup - reuse Gmail credentials location
|
||||
CREDENTIALS_PATH = Path.home() / ".gmail-mcp" / "credentials.json"
|
||||
@@ -92,9 +96,11 @@ def fetch_events(start: datetime, end: datetime, max_results: int = 50) -> list[
|
||||
start_raw = event['start'].get('dateTime', event['start'].get('date'))
|
||||
if 'T' in start_raw:
|
||||
start_dt = datetime.fromisoformat(start_raw.replace('Z', '+00:00'))
|
||||
start_local = start_dt.astimezone(LOCAL_TZ)
|
||||
all_day = False
|
||||
else:
|
||||
start_dt = datetime.strptime(start_raw, '%Y-%m-%d')
|
||||
start_local = start_dt # All-day events don't need TZ conversion
|
||||
all_day = True
|
||||
|
||||
# Parse end time
|
||||
@@ -121,7 +127,7 @@ def fetch_events(start: datetime, end: datetime, max_results: int = 50) -> list[
|
||||
'id': event['id'],
|
||||
'title': event.get('summary', '(no title)'),
|
||||
'start': start_raw,
|
||||
'start_formatted': start_dt.strftime('%I:%M %p').lstrip('0') if not all_day else 'All day',
|
||||
'start_formatted': start_local.strftime('%I:%M %p').lstrip('0') if not all_day else 'All day',
|
||||
'end': end_raw,
|
||||
'duration_mins': duration_mins,
|
||||
'all_day': all_day,
|
||||
@@ -129,8 +135,8 @@ def fetch_events(start: datetime, end: datetime, max_results: int = 50) -> list[
|
||||
'meeting_link': meeting_link,
|
||||
'attendee_count': attendee_count,
|
||||
'description': (event.get('description', '') or '')[:100],
|
||||
'date': start_dt.strftime('%Y-%m-%d'),
|
||||
'day_name': start_dt.strftime('%A'),
|
||||
'date': start_local.strftime('%Y-%m-%d'),
|
||||
'day_name': start_local.strftime('%A'),
|
||||
})
|
||||
|
||||
return events
|
||||
@@ -197,18 +203,23 @@ def delegate(model: str, system: str, prompt: str, max_tokens: int = 4096) -> di
|
||||
|
||||
def cmd_today() -> dict:
|
||||
"""Get today's events."""
|
||||
now = datetime.now(timezone.utc)
|
||||
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end = start + timedelta(days=1)
|
||||
# Use local time to determine "today"
|
||||
now_local = datetime.now(LOCAL_TZ)
|
||||
start_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end_local = start_local + timedelta(days=1)
|
||||
|
||||
events = fetch_events(start, end)
|
||||
# Convert to UTC for API query
|
||||
start_utc = start_local.astimezone(timezone.utc)
|
||||
end_utc = end_local.astimezone(timezone.utc)
|
||||
|
||||
events = fetch_events(start_utc, end_utc)
|
||||
|
||||
return {
|
||||
"tier": "haiku",
|
||||
"operation": "today",
|
||||
"date": start.strftime('%Y-%m-%d'),
|
||||
"day_name": start.strftime('%A'),
|
||||
"display_date": start.strftime('%A, %b %d'),
|
||||
"date": start_local.strftime('%Y-%m-%d'),
|
||||
"day_name": start_local.strftime('%A'),
|
||||
"display_date": start_local.strftime('%A, %b %d'),
|
||||
"events": events,
|
||||
"count": len(events)
|
||||
}
|
||||
@@ -216,18 +227,23 @@ def cmd_today() -> dict:
|
||||
|
||||
def cmd_tomorrow() -> dict:
|
||||
"""Get tomorrow's events."""
|
||||
now = datetime.now(timezone.utc)
|
||||
start = (now + timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end = start + timedelta(days=1)
|
||||
# Use local time to determine "tomorrow"
|
||||
now_local = datetime.now(LOCAL_TZ)
|
||||
start_local = (now_local + timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end_local = start_local + timedelta(days=1)
|
||||
|
||||
events = fetch_events(start, end)
|
||||
# Convert to UTC for API query
|
||||
start_utc = start_local.astimezone(timezone.utc)
|
||||
end_utc = end_local.astimezone(timezone.utc)
|
||||
|
||||
events = fetch_events(start_utc, end_utc)
|
||||
|
||||
return {
|
||||
"tier": "haiku",
|
||||
"operation": "tomorrow",
|
||||
"date": start.strftime('%Y-%m-%d'),
|
||||
"day_name": start.strftime('%A'),
|
||||
"display_date": start.strftime('%A, %b %d'),
|
||||
"date": start_local.strftime('%Y-%m-%d'),
|
||||
"day_name": start_local.strftime('%A'),
|
||||
"display_date": start_local.strftime('%A, %b %d'),
|
||||
"events": events,
|
||||
"count": len(events)
|
||||
}
|
||||
@@ -235,16 +251,21 @@ def cmd_tomorrow() -> dict:
|
||||
|
||||
def cmd_week() -> dict:
|
||||
"""Get next 7 days of events, grouped by day."""
|
||||
now = datetime.now(timezone.utc)
|
||||
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end = start + timedelta(days=7)
|
||||
# Use local time to determine the week
|
||||
now_local = datetime.now(LOCAL_TZ)
|
||||
start_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
end_local = start_local + timedelta(days=7)
|
||||
|
||||
events = fetch_events(start, end, max_results=100)
|
||||
# Convert to UTC for API query
|
||||
start_utc = start_local.astimezone(timezone.utc)
|
||||
end_utc = end_local.astimezone(timezone.utc)
|
||||
|
||||
# Group by date
|
||||
events = fetch_events(start_utc, end_utc, max_results=100)
|
||||
|
||||
# Group by date (using local dates)
|
||||
by_day = {}
|
||||
for i in range(7):
|
||||
day = start + timedelta(days=i)
|
||||
day = start_local + timedelta(days=i)
|
||||
day_str = day.strftime('%Y-%m-%d')
|
||||
by_day[day_str] = {
|
||||
"date": day_str,
|
||||
@@ -261,9 +282,9 @@ def cmd_week() -> dict:
|
||||
return {
|
||||
"tier": "haiku",
|
||||
"operation": "week",
|
||||
"start_date": start.strftime('%Y-%m-%d'),
|
||||
"end_date": end.strftime('%Y-%m-%d'),
|
||||
"display_range": f"{start.strftime('%b %d')} - {end.strftime('%b %d')}",
|
||||
"start_date": start_local.strftime('%Y-%m-%d'),
|
||||
"end_date": end_local.strftime('%Y-%m-%d'),
|
||||
"display_range": f"{start_local.strftime('%b %d')} - {end_local.strftime('%b %d')}",
|
||||
"days": list(by_day.values()),
|
||||
"total_events": len(events)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user