summaryrefslogtreecommitdiff
path: root/internal/api/google_calendar.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-25 17:15:23 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-25 17:15:23 -1000
commit4420aace9c0ee1bb3255190234f4a2035619b473 (patch)
treee5dc0fe1878984fbefeb012e235df896b63de4f0 /internal/api/google_calendar.go
parent6518a7ed5ee8800741351166a724da53cb2f271e (diff)
Fix timezone and date handling bugs #40, #41, #42
#40, #41: Fix calendar event timezone handling - Parse all-day events in local timezone using ParseInLocation - Convert timed events to local time after parsing RFC3339 - Update ComputeDaySection to normalize both now and item time to local before comparison, ensuring consistent today/tomorrow classification #42: Mobile conditions page now uses 2 columns - Changed 600px breakpoint from 1 column to 2 columns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/api/google_calendar.go')
-rw-r--r--internal/api/google_calendar.go65
1 files changed, 62 insertions, 3 deletions
diff --git a/internal/api/google_calendar.go b/internal/api/google_calendar.go
index 919976b..8217b49 100644
--- a/internal/api/google_calendar.go
+++ b/internal/api/google_calendar.go
@@ -57,12 +57,15 @@ func (c *GoogleCalendarClient) GetUpcomingEvents(ctx context.Context, maxResults
for _, item := range events.Items {
var start, end time.Time
if item.Start.DateTime == "" {
- // All-day event
- start, _ = time.Parse("2006-01-02", item.Start.Date)
- end, _ = time.Parse("2006-01-02", item.End.Date)
+ // All-day event - parse in local timezone
+ start, _ = time.ParseInLocation("2006-01-02", item.Start.Date, time.Local)
+ end, _ = time.ParseInLocation("2006-01-02", item.End.Date, time.Local)
} else {
+ // Timed event - parse RFC3339 then convert to local
start, _ = time.Parse(time.RFC3339, item.Start.DateTime)
end, _ = time.Parse(time.RFC3339, item.End.DateTime)
+ start = start.Local()
+ end = end.Local()
}
allEvents = append(allEvents, models.CalendarEvent{
@@ -101,3 +104,59 @@ func (c *GoogleCalendarClient) GetUpcomingEvents(ctx context.Context, maxResults
return uniqueEvents, nil
}
+
+func (c *GoogleCalendarClient) GetEventsByDateRange(ctx context.Context, start, end time.Time) ([]models.CalendarEvent, error) {
+ timeMin := start.Format(time.RFC3339)
+ timeMax := end.Format(time.RFC3339)
+ var allEvents []models.CalendarEvent
+
+ for _, calendarID := range c.calendarIDs {
+ events, err := c.srv.Events.List(calendarID).ShowDeleted(false).
+ SingleEvents(true).TimeMin(timeMin).TimeMax(timeMax).OrderBy("startTime").Do()
+ if err != nil {
+ log.Printf("Warning: failed to fetch events from calendar %s: %v", calendarID, err)
+ continue
+ }
+
+ for _, item := range events.Items {
+ var evtStart, evtEnd time.Time
+ if item.Start.DateTime == "" {
+ // All-day event - parse in local timezone
+ evtStart, _ = time.ParseInLocation("2006-01-02", item.Start.Date, time.Local)
+ evtEnd, _ = time.ParseInLocation("2006-01-02", item.End.Date, time.Local)
+ } else {
+ // Timed event - parse RFC3339 then convert to local
+ evtStart, _ = time.Parse(time.RFC3339, item.Start.DateTime)
+ evtEnd, _ = time.Parse(time.RFC3339, item.End.DateTime)
+ evtStart = evtStart.Local()
+ evtEnd = evtEnd.Local()
+ }
+
+ allEvents = append(allEvents, models.CalendarEvent{
+ ID: item.Id,
+ Summary: item.Summary,
+ Description: item.Description,
+ Start: evtStart,
+ End: evtEnd,
+ HTMLLink: item.HtmlLink,
+ })
+ }
+ }
+
+ // Deduplicate
+ seen := make(map[string]bool)
+ var uniqueEvents []models.CalendarEvent
+ for _, event := range allEvents {
+ key := fmt.Sprintf("%s|%d", event.Summary, event.Start.Unix())
+ if !seen[key] {
+ seen[key] = true
+ uniqueEvents = append(uniqueEvents, event)
+ }
+ }
+
+ sort.Slice(uniqueEvents, func(i, j int) bool {
+ return uniqueEvents[i].Start.Before(uniqueEvents[j].Start)
+ })
+
+ return uniqueEvents, nil
+}