Skip to content

Commit 5306b5c

Browse files
fix(calendar): support ISO 8601 time format and add 'list' alias
- Add parsing for ISO 8601 datetime with numeric timezone without colon (e.g., 2026-01-09T16:38:41-0800), which is the format produced by macOS `date +%Y-%m-%dT%H:%M:%S%z` - Add 'list' as an alias for 'events' subcommand for more intuitive CLI usage (gog calendar list instead of gog calendar events) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c55c5c8 commit 5306b5c

3 files changed

Lines changed: 21 additions & 1 deletion

File tree

internal/cmd/calendar.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
type CalendarCmd struct {
1414
Calendars CalendarCalendarsCmd `cmd:"" name:"calendars" help:"List calendars"`
1515
ACL CalendarAclCmd `cmd:"" name:"acl" help:"List calendar ACL"`
16-
Events CalendarEventsCmd `cmd:"" name:"events" help:"List events from a calendar or all calendars"`
16+
Events CalendarEventsCmd `cmd:"" name:"events" aliases:"list" help:"List events from a calendar or all calendars"`
1717
Event CalendarEventCmd `cmd:"" name:"event" help:"Get event"`
1818
Create CalendarCreateCmd `cmd:"" name:"create" help:"Create an event"`
1919
Update CalendarUpdateCmd `cmd:"" name:"update" help:"Update an event"`

internal/cmd/time_helpers.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ func ResolveTimeRangeWithDefaults(ctx context.Context, svc *calendar.Service, fl
130130

131131
// parseTimeExpr parses a time expression which can be:
132132
// - RFC3339: 2026-01-05T14:00:00-08:00
133+
// - ISO 8601 with numeric timezone: 2026-01-05T14:00:00-0800 (no colon)
133134
// - Date only: 2026-01-05 (interpreted as start of day in user's timezone)
134135
// - Relative: today, tomorrow, monday, next tuesday
135136
func parseTimeExpr(expr string, now time.Time, loc *time.Location) (time.Time, error) {
@@ -140,6 +141,12 @@ func parseTimeExpr(expr string, now time.Time, loc *time.Location) (time.Time, e
140141
return t, nil
141142
}
142143

144+
// Try ISO 8601 with numeric timezone without colon (e.g., -0800)
145+
// This is what macOS `date +%Y-%m-%dT%H:%M:%S%z` produces
146+
if t, err := time.Parse("2006-01-02T15:04:05-0700", expr); err == nil {
147+
return t, nil
148+
}
149+
143150
// Now lowercase for relative expressions
144151
exprLower := strings.ToLower(expr)
145152

internal/cmd/time_helpers_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@ func TestParseTimeExprMore(t *testing.T) {
4444
t.Fatalf("expected UTC location, got %v", parsed.Location())
4545
}
4646

47+
// Test ISO 8601 with numeric timezone without colon (macOS date +%z format)
48+
parsed, err = parseTimeExpr("2025-01-09T16:38:41-0800", now, loc)
49+
if err != nil {
50+
t.Fatalf("parseTimeExpr iso8601 numeric tz: %v", err)
51+
}
52+
if parsed.Hour() != 16 || parsed.Minute() != 38 || parsed.Second() != 41 {
53+
t.Fatalf("unexpected iso8601 numeric tz time: %v", parsed)
54+
}
55+
_, offset := parsed.Zone()
56+
if offset != -8*3600 {
57+
t.Fatalf("unexpected iso8601 numeric tz offset: %d", offset)
58+
}
59+
4760
parsed, err = parseTimeExpr("yesterday", now, loc)
4861
if err != nil {
4962
t.Fatalf("parseTimeExpr yesterday: %v", err)

0 commit comments

Comments
 (0)