From 791ddb85de9109ee8212ff0b3d9927f023218d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Furga=C5=82a?= <83299832+00200200@users.noreply.github.com> Date: Wed, 30 Sep 2026 11:41:15 +0200 Subject: [PATCH] fix: parse Unix second timestamps from numeric strings in ToTimeE Integer inputs already become time.Unix values, but the same digits as a string failed date parsing. Accept 10+ digit numeric strings (and signed equivalents) as Unix seconds after named formats miss, fixing #102. --- time.go | 19 ++++++++++++++++++- time_test.go | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/time.go b/time.go index 744cd5ac..8876e9dd 100644 --- a/time.go +++ b/time.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + "strconv" "strings" "time" @@ -30,7 +31,23 @@ func ToTimeInDefaultLocationE(i any, location *time.Location) (tim time.Time, er case time.Time: return v, nil case string: - return StringToDateInDefaultLocation(v, location) + tm, err := StringToDateInDefaultLocation(v, location) + if err == nil { + return tm, nil + } + // Integer inputs are treated as Unix seconds. Accept the same for pure + // numeric strings (see #102). Require 10+ digits so short values like + // "2006" stay date-parse errors rather than becoming timestamps. + if n, perr := strconv.ParseInt(v, 10, 64); perr == nil { + digits := len(v) + if v[0] == '+' || v[0] == '-' { + digits-- + } + if digits >= 10 { + return time.Unix(n, 0), nil + } + } + return tm, err case json.Number: // Originally this used ToInt64E, but adding string float conversion broke ToTime. // the behavior of ToTime would have changed if we continued using it. diff --git a/time_test.go b/time_test.go index a22ea980..6a8e30b6 100644 --- a/time_test.go +++ b/time_test.go @@ -56,6 +56,9 @@ func TestTime(t *testing.T) { {uint64(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false}, {uint32(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false}, {json.Number("1234567890"), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false}, + {"1234567890", time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false}, // Unix seconds as string (#102) + {"1600285405", time.Date(2020, 9, 16, 19, 43, 25, 0, time.UTC), false}, // Unix seconds as string (#102) + {"-62135596800", time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC), false}, // Unix seconds before epoch as string {time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC), false}, {ptr, time.Time{}, false},