diff --git a/values/convert.go b/values/convert.go index d7c8d7e..de14843 100644 --- a/values/convert.go +++ b/values/convert.go @@ -94,8 +94,19 @@ func Convert(value any, typ reflect.Type) (any, error) { //nolint: gocyclo return rv.Convert(typ).Interface(), nil } - if typ == timeType && rv.Kind() == reflect.String { - return ParseDate(value.(string)) + if typ == timeType { + switch rv.Kind() { + case reflect.String: + return ParseDate(value.(string)) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return time.Unix(rv.Int(), 0), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return time.Unix(int64(rv.Uint()), 0), nil + case reflect.Float32, reflect.Float64: + sec := int64(rv.Float()) + nsec := int64((rv.Float() - float64(sec)) * 1e9) + return time.Unix(sec, nsec), nil + } } // currently unused: // case reflect.PtrTo(r.Type()) == typ: diff --git a/values/convert_test.go b/values/convert_test.go index 50503c1..cde4bdb 100644 --- a/values/convert_test.go +++ b/values/convert_test.go @@ -183,6 +183,30 @@ func TestMustConvert(t *testing.T) { require.Panics(t, func() { MustConvert("x", typ) }) } +func TestConvert_intToTime(t *testing.T) { + typ := reflect.TypeOf(time.Time{}) + + // int -> time.Time + v, err := Convert(int(1152098955), typ) + require.NoError(t, err) + require.Equal(t, time.Unix(1152098955, 0), v) + + // int64 -> time.Time + v, err = Convert(int64(1152098955), typ) + require.NoError(t, err) + require.Equal(t, time.Unix(1152098955, 0), v) + + // float64 -> time.Time + v, err = Convert(float64(1152098955), typ) + require.NoError(t, err) + require.Equal(t, time.Unix(1152098955, 0), v) + + // string timestamp -> time.Time + v, err = Convert("1152098955", typ) + require.NoError(t, err) + require.Equal(t, time.Unix(1152098955, 0), v) +} + func TestMustConvertItem(t *testing.T) { v := MustConvertItem(2, []string{}) require.Equal(t, "2", v) diff --git a/values/parsedate.go b/values/parsedate.go index 762e840..f2dfd4c 100644 --- a/values/parsedate.go +++ b/values/parsedate.go @@ -2,6 +2,7 @@ package values import ( "reflect" + "strconv" "time" ) @@ -50,6 +51,10 @@ func ParseDate(s string) (time.Time, error) { return time.Now(), nil } + if sec, err := strconv.ParseInt(s, 10, 64); err == nil { + return time.Unix(sec, 0), nil + } + for _, layout := range dateLayouts { t, err := time.ParseInLocation(layout, s, time.Local) if err == nil { diff --git a/values/parsedate_test.go b/values/parsedate_test.go index ca82baf..b09b63d 100644 --- a/values/parsedate_test.go +++ b/values/parsedate_test.go @@ -2,6 +2,7 @@ package values import ( "testing" + "time" "github.com/stretchr/testify/require" ) @@ -15,3 +16,15 @@ func TestConstant(t *testing.T) { require.NoError(t, err) require.Equal(t, timeMustParse("2017-07-09T10:40:00Z"), dt) } + +func TestParseDate_numericString(t *testing.T) { + // Unix timestamp as string + dt, err := ParseDate("1152098955") + require.NoError(t, err) + require.Equal(t, time.Unix(1152098955, 0), dt) + + // Zero timestamp + dt, err = ParseDate("0") + require.NoError(t, err) + require.Equal(t, time.Unix(0, 0), dt) +}