Files
gems/opal-task/internal/engine/dateparse.go
T
joakim c99a4a2d95 Implement opal-task Phase 3: Filter and Modifier Parsing
- Add filter.go: Parse filters (+tag, -tag, attribute:value, IDs)
- Implement Filter.ToSQL() for WHERE clause generation
- Add modifier.go: Parse modifiers (set/clear attributes, add/remove tags)
- Implement Modifier.Apply() to update existing tasks
- Add dateparse.go: Smart date parsing (ISO, today, tomorrow, weekdays)
- Implement nextWeekday logic (smart Sunday interpretation)
- Update GetTasks() to accept Filter parameter
- Add CreateTaskWithModifier() for task creation with modifiers
- Add comprehensive test suite (13 new tests, all passing)
- Support filtering by status, project, priority, tags, UUIDs, display IDs
- Support modifying priority, project, dates, recurrence, tags
2026-01-04 14:48:43 +01:00

64 lines
1.9 KiB
Go

package engine
import (
"fmt"
"strings"
"time"
)
// ParseDate parses date strings with smart interpretation
// Supports: ISO dates, relative (tomorrow, today), weekdays (sun, monday)
func ParseDate(s string) (time.Time, error) {
s = strings.ToLower(strings.TrimSpace(s))
now := timeNow()
// Try ISO format first
if t, err := time.Parse("2006-01-02", s); err == nil {
return t, nil
}
// Relative dates
switch s {
case "today":
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()), nil
case "tomorrow":
tomorrow := now.AddDate(0, 0, 1)
return time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, tomorrow.Location()), nil
case "yesterday":
yesterday := now.AddDate(0, 0, -1)
return time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 0, 0, 0, 0, yesterday.Location()), nil
}
// Weekday names
weekdays := map[string]time.Weekday{
"sun": time.Sunday, "sunday": time.Sunday,
"mon": time.Monday, "monday": time.Monday,
"tue": time.Tuesday, "tuesday": time.Tuesday,
"wed": time.Wednesday, "wednesday": time.Wednesday,
"thu": time.Thursday, "thursday": time.Thursday,
"fri": time.Friday, "friday": time.Friday,
"sat": time.Saturday, "saturday": time.Saturday,
}
if targetWeekday, ok := weekdays[s]; ok {
return nextWeekday(now, targetWeekday), nil
}
return time.Time{}, fmt.Errorf("unable to parse date: %s", s)
}
// nextWeekday returns the next occurrence of the target weekday
// Smart logic: if today is Thursday and target is Sunday, returns this Sunday
// If today is Sunday and target is Sunday, returns next Sunday
func nextWeekday(from time.Time, target time.Weekday) time.Time {
// Calculate days until target
daysUntil := int(target - from.Weekday())
if daysUntil <= 0 {
daysUntil += 7 // Next week
}
next := from.AddDate(0, 0, daysUntil)
return time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location())
}