diff --git a/time.go b/time.go index 744cd5a..8876e9d 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 a22ea98..6a8e30b 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},