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:
		
							
								
								
									
										22
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								README.md
									
									
									
									
									
								
							| @ -846,9 +846,11 @@ import ( | ||||
| ) | ||||
|  | ||||
| type Person struct { | ||||
| 	Name     string    `form:"name"` | ||||
| 	Address  string    `form:"address"` | ||||
| 	Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"` | ||||
|         Name       string    `form:"name"` | ||||
|         Address    string    `form:"address"` | ||||
|         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() { | ||||
| @ -862,11 +864,13 @@ func startPage(c *gin.Context) { | ||||
| 	// If `GET`, only `Form` binding engine (`query`) used. | ||||
| 	// 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 | ||||
| 	if c.ShouldBind(&person) == nil { | ||||
| 		log.Println(person.Name) | ||||
| 		log.Println(person.Address) | ||||
| 		log.Println(person.Birthday) | ||||
| 	} | ||||
|         if c.ShouldBind(&person) == nil { | ||||
|                 log.Println(person.Name) | ||||
|                 log.Println(person.Address) | ||||
|                 log.Println(person.Birthday) | ||||
|                 log.Println(person.CreateTime) | ||||
|                 log.Println(person.UnixTime) | ||||
|         } | ||||
|  | ||||
| 	c.String(200, "Success") | ||||
| } | ||||
| @ -874,7 +878,7 @@ func startPage(c *gin.Context) { | ||||
|  | ||||
| Test it with: | ||||
| ```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 | ||||
|  | ||||
| @ -65,8 +65,15 @@ type FooStructUseNumber struct { | ||||
| } | ||||
|  | ||||
| type FooBarStructForTimeType struct { | ||||
| 	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"` | ||||
| 	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"` | ||||
| 	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 { | ||||
| @ -226,7 +233,10 @@ func TestBindingFormDefaultValue2(t *testing.T) { | ||||
| func TestBindingFormForTime(t *testing.T) { | ||||
| 	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", | ||||
| 		"/", "/", | ||||
| 		"time_foo=2017-11-15", "bar2=foo") | ||||
| @ -240,8 +250,11 @@ func TestBindingFormForTime(t *testing.T) { | ||||
|  | ||||
| func TestBindingFormForTime2(t *testing.T) { | ||||
| 	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", | ||||
| 		"/?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, int64(-62135596800), obj.TimeBar.Unix()) | ||||
| 	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{} | ||||
| 	req = requestWithBody(method, badPath, badBody) | ||||
| @ -856,6 +871,24 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s | ||||
| 	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) { | ||||
| 	b := Form | ||||
| 	assert.Equal(t, "form", b.Name()) | ||||
|  | ||||
| @ -266,6 +266,24 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val | ||||
| 		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 == "" { | ||||
| 		value.Set(reflect.ValueOf(time.Time{})) | ||||
| 		return nil | ||||
|  | ||||
		Reference in New Issue
	
	Block a user