summaryrefslogtreecommitdiff
path: root/internal/api/google_calendar.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api/google_calendar.go')
-rw-r--r--internal/api/google_calendar.go74
1 files changed, 48 insertions, 26 deletions
diff --git a/internal/api/google_calendar.go b/internal/api/google_calendar.go
index 1b1971a..d2d4355 100644
--- a/internal/api/google_calendar.go
+++ b/internal/api/google_calendar.go
@@ -17,38 +17,51 @@ import (
type GoogleCalendarClient struct {
srv *calendar.Service
calendarIDs []string
+ displayTZ *time.Location
}
-// parseEventTime extracts start/end times from a Google Calendar event, converting to local timezone
-func parseEventTime(item *calendar.Event) (start, end time.Time) {
+// parseEventTime extracts start/end times from a Google Calendar event
+func (c *GoogleCalendarClient) parseEventTime(item *calendar.Event) (start, end time.Time) {
+ displayTZ := c.displayTZ
+ if displayTZ == nil {
+ displayTZ = time.UTC
+ }
+
if item.Start.DateTime == "" {
- // 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)
+ // All-day event - parse in display timezone
+ start, _ = time.ParseInLocation("2006-01-02", item.Start.Date, displayTZ)
+ end, _ = time.ParseInLocation("2006-01-02", item.End.Date, displayTZ)
} else {
- // Timed event - use the event's timezone if specified
- var loc *time.Location
- if item.Start.TimeZone != "" {
- loc, _ = time.LoadLocation(item.Start.TimeZone)
- }
- if loc == nil {
- loc = time.Local
+ // Try RFC3339 first (includes timezone offset like "2006-01-02T15:04:05-10:00" or "Z")
+ var err error
+ start, err = time.Parse(time.RFC3339, item.Start.DateTime)
+ if err != nil {
+ // No timezone in string - use event's timezone or display timezone
+ var loc *time.Location
+ if item.Start.TimeZone != "" {
+ loc, _ = time.LoadLocation(item.Start.TimeZone)
+ }
+ if loc == nil {
+ loc = displayTZ
+ }
+ start, _ = time.ParseInLocation("2006-01-02T15:04:05", item.Start.DateTime, loc)
}
- // Try parsing with timezone offset first (RFC3339)
- start, _ = time.Parse(time.RFC3339, item.Start.DateTime)
- end, _ = time.Parse(time.RFC3339, item.End.DateTime)
-
- // If the parsed time is zero (parse failed) or missing timezone info,
- // parse in the event's timezone
- if start.IsZero() || item.Start.DateTime[len(item.Start.DateTime)-1] != 'Z' && !strings.Contains(item.Start.DateTime, "+") && !strings.Contains(item.Start.DateTime, "-") {
- start, _ = time.ParseInLocation("2006-01-02T15:04:05", item.Start.DateTime, loc)
+ end, err = time.Parse(time.RFC3339, item.End.DateTime)
+ if err != nil {
+ var loc *time.Location
+ if item.End.TimeZone != "" {
+ loc, _ = time.LoadLocation(item.End.TimeZone)
+ }
+ if loc == nil {
+ loc = displayTZ
+ }
end, _ = time.ParseInLocation("2006-01-02T15:04:05", item.End.DateTime, loc)
}
- // Convert to local timezone for display
- start = start.In(time.Local)
- end = end.In(time.Local)
+ // Convert to display timezone
+ start = start.In(displayTZ)
+ end = end.In(displayTZ)
}
return
}
@@ -72,7 +85,8 @@ func deduplicateEvents(events []models.CalendarEvent) []models.CalendarEvent {
// NewGoogleCalendarClient creates a client that fetches from multiple calendars.
// calendarIDs can be comma-separated (e.g., "cal1@group.calendar.google.com,cal2@group.calendar.google.com")
-func NewGoogleCalendarClient(ctx context.Context, credentialsFile, calendarIDs string) (*GoogleCalendarClient, error) {
+// timezone is the IANA timezone name for display (e.g., "Pacific/Honolulu")
+func NewGoogleCalendarClient(ctx context.Context, credentialsFile, calendarIDs, timezone string) (*GoogleCalendarClient, error) {
srv, err := calendar.NewService(ctx, option.WithCredentialsFile(credentialsFile))
if err != nil {
return nil, fmt.Errorf("unable to retrieve Calendar client: %v", err)
@@ -87,9 +101,17 @@ func NewGoogleCalendarClient(ctx context.Context, credentialsFile, calendarIDs s
}
}
+ // Load display timezone
+ displayTZ, err := time.LoadLocation(timezone)
+ if err != nil {
+ log.Printf("Warning: invalid timezone %q, using UTC: %v", timezone, err)
+ displayTZ = time.UTC
+ }
+
return &GoogleCalendarClient{
srv: srv,
calendarIDs: trimmedIDs,
+ displayTZ: displayTZ,
}, nil
}
@@ -106,7 +128,7 @@ func (c *GoogleCalendarClient) GetUpcomingEvents(ctx context.Context, maxResults
}
for _, item := range events.Items {
- start, end := parseEventTime(item)
+ start, end := c.parseEventTime(item)
allEvents = append(allEvents, models.CalendarEvent{
ID: item.Id,
Summary: item.Summary,
@@ -139,7 +161,7 @@ func (c *GoogleCalendarClient) GetEventsByDateRange(ctx context.Context, start,
}
for _, item := range events.Items {
- evtStart, evtEnd := parseEventTime(item)
+ evtStart, evtEnd := c.parseEventTime(item)
allEvents = append(allEvents, models.CalendarEvent{
ID: item.Id,
Summary: item.Summary,