From 58476df487c4d8f56410b112cc551ae663c88d19 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 22 Jun 2026 14:31:19 +0300 Subject: Fix due date display calendar days (oq0) --- internal/ui/table.go | 16 +++---------- internal/ui/table_test.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/internal/ui/table.go b/internal/ui/table.go index 59eaaeb..2772e2b 100644 --- a/internal/ui/table.go +++ b/internal/ui/table.go @@ -1025,23 +1025,13 @@ func (m Model) formatDue(s string, width int) string { if s == "" { return "" } - ts, err := time.Parse(task.DateFormat, s) + ts, err := parseTaskDate(s) if err != nil { return s } - days := int(time.Until(ts).Hours() / 24) - var val string - switch days { - case 0: - val = "today" - case 1: - val = "tomorrow" - case -1: - val = "yesterday" - default: - val = fmt.Sprintf("%dd", days) - } + days := daysUntil(ts) + val := formatDueText(s) style := lipgloss.NewStyle().Width(width) if days < 0 { style = style.Background(lipgloss.Color(m.theme.OverdueBG)) diff --git a/internal/ui/table_test.go b/internal/ui/table_test.go index bfd866d..9bc8150 100644 --- a/internal/ui/table_test.go +++ b/internal/ui/table_test.go @@ -74,6 +74,63 @@ func TestAnnotateHotkey(t *testing.T) { } } +func TestFormatDueUsesCalendarDayLabels(t *testing.T) { + now := time.Now() + dueOn := func(dayOffset int, hour, minute int) string { + day := now.AddDate(0, 0, dayOffset) + due := time.Date(day.Year(), day.Month(), day.Day(), hour, minute, 0, 0, time.UTC) + return due.Format(task.DateFormat) + } + skipIfDateChanged := func() { + t.Helper() + later := time.Now() + if later.Year() != now.Year() || later.YearDay() != now.YearDay() { + t.Skip("local date changed during due-date boundary test") + } + } + + m := Model{theme: DefaultTheme()} + tests := []struct { + name string + due string + want string + }{ + { + name: "late yesterday", + due: dueOn(-1, 23, 59), + want: "yesterday", + }, + { + name: "early today", + due: dueOn(0, 0, 1), + want: "today", + }, + { + name: "late tomorrow", + due: dueOn(1, 23, 59), + want: "tomorrow", + }, + { + name: "future day count", + due: dueOn(3, 23, 59), + want: "3d", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := strings.TrimSpace(ansi.Strip(m.formatDue(tt.due, 12))) + skipIfDateChanged() + if got != tt.want { + t.Fatalf("formatDue() = %q, want %q", got, tt.want) + } + if got != formatDueText(tt.due) { + t.Fatalf("formatDue() = %q, formatDueText() = %q", got, formatDueText(tt.due)) + } + }) + } +} + func TestReplaceAnnotationHotkey(t *testing.T) { tmp := t.TempDir() taskPath := filepath.Join(tmp, "task") -- cgit v1.2.3