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