From 415b9cf310e73a12a73f59f7d63439e0702df5b0 Mon Sep 17 00:00:00 2001 From: Victor Popkov Date: Wed, 22 Jun 2016 16:32:37 +0300 Subject: [PATCH] add support for time.Time pointer in struct types Allow to use pointer *time.Time as a type in combination with orm tags in struct. This enables to treat them as "empty" in JSON marshaling/unmarshaling when using 'json:"null,omitempty'. --- orm/db.go | 11 ++++++++++- orm/models_test.go | 3 +++ orm/models_utils.go | 2 ++ orm/orm_test.go | 12 ++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/orm/db.go b/orm/db.go index 78c72e87..9964e263 100644 --- a/orm/db.go +++ b/orm/db.go @@ -243,6 +243,9 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val if fi.isFielder { f := field.Addr().Interface().(Fielder) f.SetRaw(tnow.In(DefaultTimeLoc)) + } else if field.Kind() == reflect.Ptr { + v := tnow.In(DefaultTimeLoc) + field.Set(reflect.ValueOf(&v)) } else { field.Set(reflect.ValueOf(tnow.In(DefaultTimeLoc))) } @@ -1273,8 +1276,14 @@ setValue: if isNative { if value == nil { value = time.Time{} + } else if field.Kind() == reflect.Ptr { + if value != nil { + v := value.(time.Time) + field.Set(reflect.ValueOf(&v)) + } + } else { + field.Set(reflect.ValueOf(value)) } - field.Set(reflect.ValueOf(value)) } case fieldType == TypePositiveBitField && field.Kind() == reflect.Ptr: if value != nil { diff --git a/orm/models_test.go b/orm/models_test.go index c68c7339..462370b2 100644 --- a/orm/models_test.go +++ b/orm/models_test.go @@ -181,6 +181,9 @@ type DataNull struct { Float32Ptr *float32 `orm:"null"` Float64Ptr *float64 `orm:"null"` DecimalPtr *float64 `orm:"digits(8);decimals(4);null"` + TimePtr *time.Time `orm:"null;type(time)"` + DatePtr *time.Time `orm:"null;type(date)"` + DateTimePtr *time.Time `orm:"null"` } type String string diff --git a/orm/models_utils.go b/orm/models_utils.go index 1dc17f81..4c4b0f24 100644 --- a/orm/models_utils.go +++ b/orm/models_utils.go @@ -137,6 +137,8 @@ func getFieldType(val reflect.Value) (ft int, err error) { ft = TypeBooleanField case reflect.TypeOf(new(string)): ft = TypeCharField + case reflect.TypeOf(new(time.Time)): + ft = TypeDateTimeField default: elm := reflect.Indirect(val) switch elm.Kind() { diff --git a/orm/orm_test.go b/orm/orm_test.go index e1ecdfd1..b5973448 100644 --- a/orm/orm_test.go +++ b/orm/orm_test.go @@ -350,6 +350,9 @@ func TestNullDataTypes(t *testing.T) { throwFail(t, AssertIs(d.Float32Ptr, nil)) throwFail(t, AssertIs(d.Float64Ptr, nil)) throwFail(t, AssertIs(d.DecimalPtr, nil)) + throwFail(t, AssertIs(d.TimePtr, nil)) + throwFail(t, AssertIs(d.DatePtr, nil)) + throwFail(t, AssertIs(d.DateTimePtr, nil)) _, err = dORM.Raw(`INSERT INTO data_null (boolean) VALUES (?)`, nil).Exec() throwFail(t, err) @@ -376,6 +379,9 @@ func TestNullDataTypes(t *testing.T) { float32Ptr := float32(42.0) float64Ptr := float64(42.0) decimalPtr := float64(42.0) + timePtr := time.Now() + datePtr := time.Now() + dateTimePtr := time.Now() d = DataNull{ DateTime: time.Now(), @@ -401,6 +407,9 @@ func TestNullDataTypes(t *testing.T) { Float32Ptr: &float32Ptr, Float64Ptr: &float64Ptr, DecimalPtr: &decimalPtr, + TimePtr: &timePtr, + DatePtr: &datePtr, + DateTimePtr: &dateTimePtr, } id, err = dORM.Insert(&d) @@ -441,6 +450,9 @@ func TestNullDataTypes(t *testing.T) { throwFail(t, AssertIs(*d.Float32Ptr, float32Ptr)) throwFail(t, AssertIs(*d.Float64Ptr, float64Ptr)) throwFail(t, AssertIs(*d.DecimalPtr, decimalPtr)) + throwFail(t, AssertIs((*d.TimePtr).Format(testTime), timePtr.Format(testTime))) + throwFail(t, AssertIs((*d.DatePtr).Format(testDate), datePtr.Format(testDate))) + throwFail(t, AssertIs((*d.DateTimePtr).Format(testDateTime), dateTimePtr.Format(testDateTime))) } func TestDataCustomTypes(t *testing.T) {