From 73d2b7ed06fb59ebfa815544badbb9523b74d70a Mon Sep 17 00:00:00 2001 From: John Guo Date: Mon, 30 Aug 2021 22:26:02 +0800 Subject: [PATCH] fix issue #1387 --- database/gdb/gdb_func.go | 7 +++- database/gdb/gdb_model_insert.go | 3 ++ database/gdb/gdb_z_mysql_model_test.go | 41 +++++++++++++++++++ os/gtime/gtime.go | 5 ++- os/gtime/gtime_time.go | 7 ++++ ...nv_z_unit_struct_marshal_unmarshal_test.go | 3 +- util/gconv/gconv_z_unit_struct_test.go | 16 ++++++++ 7 files changed, 79 insertions(+), 3 deletions(-) diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index 37ae7a8c3..87c6e8763 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -209,7 +209,12 @@ func ConvertDataForTableRecord(value interface{}) map[string]interface{} { data[k] = nil } - case *time.Time, *gtime.Time: + case *gtime.Time: + if r.IsZero() { + data[k] = nil + } + + case *time.Time: continue case Counter, *Counter: diff --git a/database/gdb/gdb_model_insert.go b/database/gdb/gdb_model_insert.go index 5c40a7eba..78099b4e6 100644 --- a/database/gdb/gdb_model_insert.go +++ b/database/gdb/gdb_model_insert.go @@ -83,8 +83,10 @@ func (m *Model) Data(data ...interface{}) *Model { list[i] = ConvertDataForTableRecord(rv.Index(i).Interface()) } model.data = list + case reflect.Map: model.data = ConvertDataForTableRecord(data[0]) + case reflect.Struct: if v, ok := data[0].(apiInterfaces); ok { var ( @@ -98,6 +100,7 @@ func (m *Model) Data(data ...interface{}) *Model { } else { model.data = ConvertDataForTableRecord(data[0]) } + default: model.data = data[0] } diff --git a/database/gdb/gdb_z_mysql_model_test.go b/database/gdb/gdb_z_mysql_model_test.go index ee079006a..f9f95fcef 100644 --- a/database/gdb/gdb_z_mysql_model_test.go +++ b/database/gdb/gdb_z_mysql_model_test.go @@ -3871,3 +3871,44 @@ func Test_Model_FieldAvg(t *testing.T) { t.Assert(all[0]["total"], 1) }) } + +// https://github.com/gogf/gf/issues/1387 +func Test_Model_GTime_DefaultValue(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Passport string + Password string + Nickname string + CreateTime *gtime.Time + } + data := User{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + Nickname: "name_1", + } + // Insert + _, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + + // Select + var ( + user *User + ) + err = db.Model(table).Scan(&user) + t.AssertNil(err) + t.Assert(user.Passport, data.Passport) + t.Assert(user.Password, data.Password) + t.Assert(user.CreateTime, data.CreateTime) + t.Assert(user.Nickname, data.Nickname) + + // Insert + user.Id = 2 + _, err = db.Model(table).Data(user).Insert() + t.AssertNil(err) + }) +} diff --git a/os/gtime/gtime.go b/os/gtime/gtime.go index cb164da44..318704c83 100644 --- a/os/gtime/gtime.go +++ b/os/gtime/gtime.go @@ -197,7 +197,7 @@ func ISO8601() string { return time.Now().Format("2006-01-02T15:04:05-07:00") } -// ISO8601 returns current datetime in RFC822 format like "Mon, 02 Jan 06 15:04 MST". +// RFC822 returns current datetime in RFC822 format like "Mon, 02 Jan 06 15:04 MST". func RFC822() string { return time.Now().Format("Mon, 02 Jan 06 15:04 MST") } @@ -238,6 +238,9 @@ func parseDateStr(s string) (year, month, day int) { // If is not given, it converts string as a "standard" datetime string. // Note that, it fails and returns error if there's no date string in . func StrToTime(str string, format ...string) (*Time, error) { + if str == "" { + return &Time{wrapper{time.Time{}}}, nil + } if len(format) > 0 { return StrToTimeFormat(str, format[0]) } diff --git a/os/gtime/gtime_time.go b/os/gtime/gtime_time.go index 185c9dbd9..33e0de5e4 100644 --- a/os/gtime/gtime_time.go +++ b/os/gtime/gtime_time.go @@ -33,10 +33,13 @@ func New(param ...interface{}) *Time { return NewFromTime(r) case *time.Time: return NewFromTime(*r) + case Time: return &r + case *Time: return r + case string: if len(param) > 1 { switch t := param[1].(type) { @@ -47,6 +50,7 @@ func New(param ...interface{}) *Time { } } return NewFromStr(r) + case []byte: if len(param) > 1 { switch t := param[1].(type) { @@ -57,10 +61,13 @@ func New(param ...interface{}) *Time { } } return NewFromStr(string(r)) + case int: return NewFromTimeStamp(int64(r)) + case int64: return NewFromTimeStamp(r) + default: if v, ok := r.(apiUnixNano); ok { return NewFromTimeStamp(v.UnixNano()) diff --git a/util/gconv/gconv_z_unit_struct_marshal_unmarshal_test.go b/util/gconv/gconv_z_unit_struct_marshal_unmarshal_test.go index b7c0941f5..118022f82 100644 --- a/util/gconv/gconv_z_unit_struct_marshal_unmarshal_test.go +++ b/util/gconv/gconv_z_unit_struct_marshal_unmarshal_test.go @@ -46,7 +46,8 @@ func Test_Struct_UnmarshalValue1(t *testing.T) { gtest.C(t, func(t *gtest.T) { st := &MyTimeSt{} err := gconv.Struct(g.Map{"ServiceDate": nil}, st) - t.AssertNE(err, nil) + t.AssertNil(err) + t.Assert(st.ServiceDate.Time.IsZero(), true) }) gtest.C(t, func(t *gtest.T) { st := &MyTimeSt{} diff --git a/util/gconv/gconv_z_unit_struct_test.go b/util/gconv/gconv_z_unit_struct_test.go index d1d12d46d..9c7ff0713 100644 --- a/util/gconv/gconv_z_unit_struct_test.go +++ b/util/gconv/gconv_z_unit_struct_test.go @@ -639,6 +639,22 @@ func Test_Struct_Time(t *testing.T) { }) } +func Test_Struct_GTime(t *testing.T) { + // https://github.com/gogf/gf/issues/1387 + gtest.C(t, func(t *gtest.T) { + type User struct { + Name string + CreateTime *gtime.Time + } + var user *User + err := gconv.Struct(`{"Name":"John","CreateTime":""}`, &user) + t.AssertNil(err) + t.AssertNE(user, nil) + t.Assert(user.Name, `John`) + t.Assert(user.CreateTime, nil) + }) +} + // Auto create struct when given pointer. func Test_Struct_Create(t *testing.T) { gtest.C(t, func(t *gtest.T) {