string to time duration hook
diff --git a/decode_hooks.go b/decode_hooks.go index 9cdc2c9..aa91f76 100644 --- a/decode_hooks.go +++ b/decode_hooks.go
@@ -5,6 +5,7 @@ "reflect" "strconv" "strings" + "time" ) // typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns @@ -98,6 +99,25 @@ } } +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + func WeaklyTypedHook( f reflect.Kind, t reflect.Kind,
diff --git a/decode_hooks_test.go b/decode_hooks_test.go index 84e3fc5..53289af 100644 --- a/decode_hooks_test.go +++ b/decode_hooks_test.go
@@ -4,6 +4,7 @@ "errors" "reflect" "testing" + "time" ) func TestComposeDecodeHookFunc(t *testing.T) { @@ -123,6 +124,35 @@ } } +func TestStringToTimeDurationHookFunc(t *testing.T) { + f := StringToTimeDurationHookFunc() + + strType := reflect.TypeOf("") + timeType := reflect.TypeOf(time.Duration(5)) + cases := []struct { + f, t reflect.Type + data interface{} + result interface{} + err bool + }{ + {strType, timeType, "5s", 5 * time.Second, false}, + {strType, timeType, "5", time.Duration(0), true}, + {strType, strType, "5", "5", false}, + } + + for i, tc := range cases { + actual, err := DecodeHookExec(f, tc.f, tc.t, tc.data) + if tc.err != (err != nil) { + t.Fatalf("case %d: expected err %#v", i, tc.err) + } + if !reflect.DeepEqual(actual, tc.result) { + t.Fatalf( + "case %d: expected %#v, got %#v", + i, tc.result, actual) + } + } +} + func TestWeaklyTypedHook(t *testing.T) { var f DecodeHookFunc = WeaklyTypedHook