fix(v0.5.1): use local time for workspace directory prefix and info display

Workspace directory names (YYYY-MM-DD_slug) and the YYYYMMDD-HHMMSS ID
field now use local time so users see their wall-clock date rather
than UTC — the prior behavior caused evening-EST creations to appear
under tomorrow's date for several hours every day. ctask info's
Created/Updated/Archived lines also convert to local for display.

Stored timestamps in task.yaml, session logs, the lease, the manifest,
and the session summary all continue to use UTC. Only user-facing
surfaces change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 21:33:52 -04:00
parent 8130a689d4
commit a162aec0b2
4 changed files with 101 additions and 6 deletions
+7 -3
View File
@@ -62,9 +62,13 @@ func Create(opts CreateOpts) (*CreateResult, error) {
slug = "task"
}
now := time.Now().UTC()
date := now.Format("2006-01-02")
id := now.Format("20060102-150405")
// v0.5.1: directory prefix and ID use local time so users see their
// wall-clock date rather than UTC. Stored task.yaml timestamps still
// use UTC (see meta below) for unambiguous machine-readable format.
nowLocal := time.Now()
date := nowLocal.Format("2006-01-02")
id := nowLocal.Format("20060102-150405")
now := nowLocal.UTC()
categoryDir := opts.Root
if !opts.SkipCategoryDir {
+38
View File
@@ -5,6 +5,7 @@ import (
"path/filepath"
"strings"
"testing"
"time"
)
func TestCreateWorkspace(t *testing.T) {
@@ -372,6 +373,43 @@ func TestCreateProjectSubdirMatchesSuffixedSlug(t *testing.T) {
}
}
func TestCreateDirectoryPrefixUsesLocalDate(t *testing.T) {
// v0.5.1: directory prefix must use local-time date so users see
// their wall-clock date rather than UTC date on evening EST runs.
root := t.TempDir()
expected := time.Now().Format("2006-01-02") // LOCAL — no .UTC()
res, err := Create(CreateOpts{
Root: root, Title: "tz-check", Category: "general",
Mode: "local", Agent: "claude",
})
if err != nil {
t.Fatalf("Create: %v", err)
}
dirBase := filepath.Base(res.Path)
if !strings.HasPrefix(dirBase, expected) {
t.Errorf("directory %q should start with local-date prefix %q", dirBase, expected)
}
}
func TestCreateStoresTimestampsInUTC(t *testing.T) {
// v0.5.1: even though the directory prefix is local, stored task.yaml
// timestamps must remain UTC (unambiguous machine-readable format).
root := t.TempDir()
res, err := Create(CreateOpts{
Root: root, Title: "tz-check-stored", Category: "general",
Mode: "local", Agent: "claude",
})
if err != nil {
t.Fatalf("Create: %v", err)
}
if got := res.Meta.CreatedAt.Location(); got != time.UTC {
t.Errorf("CreatedAt location: got %v, want UTC", got)
}
if got := res.Meta.UpdatedAt.Location(); got != time.UTC {
t.Errorf("UpdatedAt location: got %v, want UTC", got)
}
}
func TestCreateTaskDoesNotScaffoldSubdir(t *testing.T) {
root := t.TempDir()
res, err := Create(CreateOpts{