mirror of https://github.com/gin-gonic/gin.git
binding: support unix time (#1980)
* binding: support unix time ref:#1979 * binding: support unix time add test file modify readme ```golang package main import ( "fmt" "github.com/gin-gonic/gin" "time" ) type shareTime struct { CreateTime time.Time `form:"createTime" time_format:"unixNano"` UnixTime time.Time `form:"unixTime" time_format:"unix"` } func main() { r := gin.Default() unix := r.Group("/unix") testCT := time.Date(2019, 7, 6, 16, 0, 33, 123, time.Local) fmt.Printf("%d\n", testCT.UnixNano()) testUT := time.Date(2019, 7, 6, 16, 0, 33, 0, time.Local) fmt.Printf("%d\n", testUT.Unix()) unix.GET("/nano", func(c *gin.Context) { s := shareTime{} c.ShouldBindQuery(&s) if !testCT.Equal(s.CreateTime) { c.String(500, "want %d got %d", testCT.UnixNano(), s.CreateTime) return } c.JSON(200, s) }) unix.GET("/sec", func(c *gin.Context) { s := shareTime{} c.ShouldBindQuery(&s) if !testUT.Equal(s.UnixTime) { c.String(500, "want %d got %d", testCT.Unix(), s.UnixTime) return } c.JSON(200, s) }) r.Run() } ``` * Contraction variable scope
This commit is contained in:
parent
0349de518b
commit
502c898d75
22
README.md
22
README.md
|
@ -846,9 +846,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Person struct {
|
type Person struct {
|
||||||
Name string `form:"name"`
|
Name string `form:"name"`
|
||||||
Address string `form:"address"`
|
Address string `form:"address"`
|
||||||
Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
|
Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
|
||||||
|
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
|
||||||
|
UnixTime time.Time `form:"unixTime" time_format:"unix"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -862,11 +864,13 @@ func startPage(c *gin.Context) {
|
||||||
// If `GET`, only `Form` binding engine (`query`) used.
|
// If `GET`, only `Form` binding engine (`query`) used.
|
||||||
// If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`).
|
// If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`).
|
||||||
// See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48
|
// See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48
|
||||||
if c.ShouldBind(&person) == nil {
|
if c.ShouldBind(&person) == nil {
|
||||||
log.Println(person.Name)
|
log.Println(person.Name)
|
||||||
log.Println(person.Address)
|
log.Println(person.Address)
|
||||||
log.Println(person.Birthday)
|
log.Println(person.Birthday)
|
||||||
}
|
log.Println(person.CreateTime)
|
||||||
|
log.Println(person.UnixTime)
|
||||||
|
}
|
||||||
|
|
||||||
c.String(200, "Success")
|
c.String(200, "Success")
|
||||||
}
|
}
|
||||||
|
@ -874,7 +878,7 @@ func startPage(c *gin.Context) {
|
||||||
|
|
||||||
Test it with:
|
Test it with:
|
||||||
```sh
|
```sh
|
||||||
$ curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15"
|
$ curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Bind Uri
|
### Bind Uri
|
||||||
|
|
|
@ -65,8 +65,15 @@ type FooStructUseNumber struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type FooBarStructForTimeType struct {
|
type FooBarStructForTimeType struct {
|
||||||
TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
|
TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
|
||||||
TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
|
TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
|
||||||
|
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
|
||||||
|
UnixTime time.Time `form:"unixTime" time_format:"unix"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooStructForTimeTypeNotUnixFormat struct {
|
||||||
|
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
|
||||||
|
UnixTime time.Time `form:"unixTime" time_format:"unix"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FooStructForTimeTypeNotFormat struct {
|
type FooStructForTimeTypeNotFormat struct {
|
||||||
|
@ -226,7 +233,10 @@ func TestBindingFormDefaultValue2(t *testing.T) {
|
||||||
func TestBindingFormForTime(t *testing.T) {
|
func TestBindingFormForTime(t *testing.T) {
|
||||||
testFormBindingForTime(t, "POST",
|
testFormBindingForTime(t, "POST",
|
||||||
"/", "/",
|
"/", "/",
|
||||||
"time_foo=2017-11-15&time_bar=", "bar2=foo")
|
"time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "bar2=foo")
|
||||||
|
testFormBindingForTimeNotUnixFormat(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
|
||||||
testFormBindingForTimeNotFormat(t, "POST",
|
testFormBindingForTimeNotFormat(t, "POST",
|
||||||
"/", "/",
|
"/", "/",
|
||||||
"time_foo=2017-11-15", "bar2=foo")
|
"time_foo=2017-11-15", "bar2=foo")
|
||||||
|
@ -240,8 +250,11 @@ func TestBindingFormForTime(t *testing.T) {
|
||||||
|
|
||||||
func TestBindingFormForTime2(t *testing.T) {
|
func TestBindingFormForTime2(t *testing.T) {
|
||||||
testFormBindingForTime(t, "GET",
|
testFormBindingForTime(t, "GET",
|
||||||
"/?time_foo=2017-11-15&time_bar=", "/?bar2=foo",
|
"/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "/?bar2=foo",
|
||||||
"", "")
|
"", "")
|
||||||
|
testFormBindingForTimeNotUnixFormat(t, "POST",
|
||||||
|
"/", "/",
|
||||||
|
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
|
||||||
testFormBindingForTimeNotFormat(t, "GET",
|
testFormBindingForTimeNotFormat(t, "GET",
|
||||||
"/?time_foo=2017-11-15", "/?bar2=foo",
|
"/?time_foo=2017-11-15", "/?bar2=foo",
|
||||||
"", "")
|
"", "")
|
||||||
|
@ -849,6 +862,8 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
|
||||||
assert.Equal(t, "Asia/Chongqing", obj.TimeFoo.Location().String())
|
assert.Equal(t, "Asia/Chongqing", obj.TimeFoo.Location().String())
|
||||||
assert.Equal(t, int64(-62135596800), obj.TimeBar.Unix())
|
assert.Equal(t, int64(-62135596800), obj.TimeBar.Unix())
|
||||||
assert.Equal(t, "UTC", obj.TimeBar.Location().String())
|
assert.Equal(t, "UTC", obj.TimeBar.Location().String())
|
||||||
|
assert.Equal(t, int64(1562400033000000123), obj.CreateTime.UnixNano())
|
||||||
|
assert.Equal(t, int64(1562400033), obj.UnixTime.Unix())
|
||||||
|
|
||||||
obj = FooBarStructForTimeType{}
|
obj = FooBarStructForTimeType{}
|
||||||
req = requestWithBody(method, badPath, badBody)
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
@ -856,6 +871,24 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
|
b := Form
|
||||||
|
assert.Equal(t, "form", b.Name())
|
||||||
|
|
||||||
|
obj := FooStructForTimeTypeNotUnixFormat{}
|
||||||
|
req := requestWithBody(method, path, body)
|
||||||
|
if method == "POST" {
|
||||||
|
req.Header.Add("Content-Type", MIMEPOSTForm)
|
||||||
|
}
|
||||||
|
err := b.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
obj = FooStructForTimeTypeNotUnixFormat{}
|
||||||
|
req = requestWithBody(method, badPath, badBody)
|
||||||
|
err = JSON.Bind(req, &obj)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) {
|
func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) {
|
||||||
b := Form
|
b := Form
|
||||||
assert.Equal(t, "form", b.Name())
|
assert.Equal(t, "form", b.Name())
|
||||||
|
|
|
@ -266,6 +266,24 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val
|
||||||
timeFormat = time.RFC3339
|
timeFormat = time.RFC3339
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch tf := strings.ToLower(timeFormat); tf {
|
||||||
|
case "unix", "unixnano":
|
||||||
|
tv, err := strconv.ParseInt(val, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d := time.Duration(1)
|
||||||
|
if tf == "unixnano" {
|
||||||
|
d = time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
t := time.Unix(tv/int64(d), tv%int64(d))
|
||||||
|
value.Set(reflect.ValueOf(t))
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if val == "" {
|
if val == "" {
|
||||||
value.Set(reflect.ValueOf(time.Time{}))
|
value.Set(reflect.ValueOf(time.Time{}))
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue