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:
		| @ -849,6 +849,8 @@ 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() { | ||||||
| @ -866,6 +868,8 @@ func startPage(c *gin.Context) { | |||||||
|                 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 | ||||||
|  | |||||||
| @ -67,6 +67,13 @@ 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 | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user