diff --git a/doc/content/en/type/time.md b/doc/content/en/type/time.md index 7182aa6..7212963 100644 --- a/doc/content/en/type/time.md +++ b/doc/content/en/type/time.md @@ -6,12 +6,10 @@ weight: 50 {{< toc >}} +## Time -## Function -- Time -- TimeE +## TimeE -## Examples ```go cvt.Time("2009-11-10 23:00:00 +0000 UTC") cvt.Time("2018-10-21T23:21:29+0200") @@ -24,5 +22,12 @@ cvt.Time(1482597504) cvt.Time(time.Date(2009, 2, 13, 23, 31, 30, 0, time.Local)) ``` +## TimeInLocation +cvt.TimeInLocation("2009-02-13 23:31:30", time.FixedZone("UTC", 8*3600)) + +## TimeInLocationE +cvt.TimeInLocationE("2009-02-13 23:31:30", time.FixedZone("UTC", 8*3600)) + + > More case see unit: `time_test.go` diff --git a/doc/content/zh-cn/type/time.md b/doc/content/zh-cn/type/time.md index aec8f34..e5deddd 100644 --- a/doc/content/zh-cn/type/time.md +++ b/doc/content/zh-cn/type/time.md @@ -6,12 +6,10 @@ weight: 50 {{< toc >}} +## Time -## 方法 -- Time -- TimeE +## TimeE -## 示例 ```go cvt.Time("2009-11-10 23:00:00 +0000 UTC") cvt.Time("2018-10-21T23:21:29+0200") @@ -34,5 +32,12 @@ cvt.Time(json.Number("1234567890")) cvt.Time(json.Number("2016-03-06 15:28:01")) ``` +## TimeInLocation +cvt.TimeInLocation("2009-02-13 23:31:30", time.FixedZone("UTC", 8*3600)) + +## TimeInLocationE +cvt.TimeInLocationE("2009-02-13 23:31:30", time.FixedZone("UTC", 8*3600)) + + > 更多示例请看单元测试:`time_test.go` diff --git a/map.go b/map.go index b660eb8..0e4d951 100644 --- a/map.go +++ b/map.go @@ -5,6 +5,48 @@ import ( "reflect" ) +// IntMapE convert an interface to `map[int]interface{}` +// * Support JSON string of map +// * Support any `map` type +func IntMapE(val interface{}) (m map[int]interface{}, err error) { + m = make(map[int]interface{}) + if val == nil { + return nil, errUnsupportedTypeNil + } + + // direct type(for improve performance) + switch v := val.(type) { + case map[int]interface{}: + return v, nil + } + + // indirect type + _, rv := Indirect(val) + switch rv.Kind() { + case reflect.Map: + var idx int + for _, key := range rv.MapKeys() { + idx, err = IntE(key.Interface()) + if err != nil { + return + } + m[idx] = rv.MapIndex(key).Interface() + } + case reflect.Slice: + // []byte + // Example: []byte(`{1:"bob",2:18}`) + if rv.Type().Elem().Kind() == reflect.Uint8 { + err = json.Unmarshal(rv.Bytes(), &m) + } + case reflect.String: + // JSON string of map + // Example: `{1:"bob",2:18}` + err = json.Unmarshal([]byte(rv.String()), &m) + } + + return +} + // StringMapE convert an interface to `map[string]interface{}` // * Support JSON string of map // * Support any `map` type @@ -37,12 +79,14 @@ func StringMapE(val interface{}) (m map[string]interface{}, err error) { case reflect.Struct: m = struct2map(rv) case reflect.Slice: - // []byte + // []byte, JSON + // Example: []byte(`{"name":"bob","age":18}`) if rv.Type().Elem().Kind() == reflect.Uint8 { err = json.Unmarshal(rv.Bytes(), &m) } case reflect.String: // JSON string of map + // Example: `{"name":"bob","age":18}` err = json.Unmarshal([]byte(rv.String()), &m) } diff --git a/map_test.go b/map_test.go index c0f470f..60bea3d 100644 --- a/map_test.go +++ b/map_test.go @@ -2,8 +2,9 @@ package cvt_test import ( "fmt" - "github.com/shockerli/cvt" "testing" + + "github.com/shockerli/cvt" ) func TestStringMapE(t *testing.T) { @@ -89,3 +90,47 @@ func TestStringMapE(t *testing.T) { assertEqual(t, tt.expect, v, "[WithE] "+msg) } } + +func TestIntMapE(t *testing.T) { + tests := []struct { + input interface{} + expect map[int]interface{} + isErr bool + }{ + // JSON + {`{"1":"cvt","2":3.21}`, map[int]interface{}{1: "cvt", 2: 3.21}, false}, + {`{"1":"cvt","2":"convert"}`, map[int]interface{}{1: "cvt", 2: "convert"}, false}, + {`{"1":"cvt","2":true}`, map[int]interface{}{1: "cvt", 2: true}, false}, + {[]byte(`{"1":"cvt","2":true}`), map[int]interface{}{1: "cvt", 2: true}, false}, + {AliasTypeString(`{"1":"cvt","2":true}`), map[int]interface{}{1: "cvt", 2: true}, false}, + {AliasTypeBytes(`{"1":"cvt","2":true}`), map[int]interface{}{1: "cvt", 2: true}, false}, + + // Map + {map[int]interface{}{}, map[int]interface{}{}, false}, + {map[int]interface{}{1: "cvt", 2: 3.21}, map[int]interface{}{1: "cvt", 2: 3.21}, false}, + {map[interface{}]interface{}{1: "cvt", 2: 3.21}, map[int]interface{}{1: "cvt", 2: 3.21}, false}, + {map[interface{}]interface{}{"1": "cvt", "2": 3.21}, map[int]interface{}{1: "cvt", 2: 3.21}, false}, + + // errors + {nil, nil, true}, + {map[interface{}]interface{}{"name": "cvt", 3.21: 3.21}, map[int]interface{}{1: "cvt", 2: 3.21}, true}, + {"", nil, true}, + {"hello", nil, true}, + } + + for i, tt := range tests { + msg := fmt.Sprintf( + "i = %d, input[%+v], expect[%+v], isErr[%v]", + i, tt.input, tt.expect, tt.isErr, + ) + + v, err := cvt.IntMapE(tt.input) + if tt.isErr { + assertError(t, err, "[HasErr] "+msg) + continue + } + + assertNoError(t, err, "[NoErr] "+msg) + assertEqual(t, tt.expect, v, "[WithE] "+msg) + } +} diff --git a/time_test.go b/time_test.go index af5bc2c..62d2d22 100644 --- a/time_test.go +++ b/time_test.go @@ -58,6 +58,10 @@ func TestTimeInLocation_BaseLine(t *testing.T) { } func TestTimeInLocationE(t *testing.T) { + var ( + locUTC8 = time.FixedZone("UTC", 8*3600) + ) + tests := []struct { input interface{} loc *time.Location @@ -65,6 +69,9 @@ func TestTimeInLocationE(t *testing.T) { isErr bool }{ {nil, nil, time.Time{}, false}, + {"2009-11-10 23:00:00 +0800", nil, time.Date(2009, 11, 10, 23, 0, 0, 0, locUTC8), false}, // Time.String() + {"2009-02-13 23:31:30", locUTC8, time.Date(2009, 2, 13, 23, 31, 30, 0, locUTC8), false}, + {"2009-02-13 23:31:30", locUTC8, time.Date(2009, 2, 13, 23, 31, 30, 0, locUTC8), false}, // errors {"2006", nil, time.Time{}, true},