Files
joakim b02c40f716 feat: improve CLI output with relative dates, rich feedback, and recurring task info
Add relative date formatting (today, tomorrow, in 3d, etc.) for list and
detail views. Add structured feedback helpers for add/complete/delete
operations showing display IDs and parsed modifiers. Change Complete() to
return spawned recurring instance so callers can display recurrence info.
Add AppendTask to working set for immediate display ID assignment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 13:44:56 +01:00

46 lines
1.2 KiB
Go

package engine
import (
"fmt"
"math"
"time"
)
// FormatRelativeDate returns a human-readable relative date string.
// Within 14 days: "today", "tomorrow", "yesterday", "in 3d", "2d ago"
// Beyond 14 days: "Feb 28", "Mar 15"
// Cross-year: "Feb 28 2027"
func FormatRelativeDate(t time.Time) string {
now := timeNow()
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
target := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
days := int(math.Round(target.Sub(today).Hours() / 24))
switch {
case days == 0:
return "today"
case days == 1:
return "tomorrow"
case days == -1:
return "yesterday"
case days > 1 && days <= 14:
return fmt.Sprintf("in %dd", days)
case days < -1 && days >= -14:
return fmt.Sprintf("%dd ago", -days)
default:
if t.Year() != now.Year() {
return t.Format("Jan 2 2006")
}
return t.Format("Jan 2")
}
}
// FormatDateWithRelative returns "2026-02-20 (in 2 days)" style.
// Used in info/detail views where both absolute and relative are useful.
func FormatDateWithRelative(t time.Time) string {
absolute := t.Format("2006-01-02 15:04")
relative := FormatRelativeDate(t)
return fmt.Sprintf("%s (%s)", absolute, relative)
}