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