From 7bb883b665082c0506991f8c87e5f02d86254920 Mon Sep 17 00:00:00 2001 From: lninl Date: Thu, 30 Jul 2020 17:39:57 +0800 Subject: [PATCH] Auto creating/updating time with unix (milli) second (#3213) * Auto creating/updating time with unix (milli) second * add test for 'Auto creating/updating time with unix (milli) second' --- callbacks/update.go | 10 +++++++--- schema/field.go | 13 +++++++++++-- tests/customize_field_test.go | 36 +++++++++++++++++++++++------------ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/callbacks/update.go b/callbacks/update.go index e492cfc9..12806af6 100644 --- a/callbacks/update.go +++ b/callbacks/update.go @@ -140,7 +140,7 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) { if !updatingValue.CanAddr() || stmt.Dest != stmt.Model { switch stmt.ReflectValue.Kind() { case reflect.Slice, reflect.Array: - var priamryKeyExprs []clause.Expression + var primaryKeyExprs []clause.Expression for i := 0; i < stmt.ReflectValue.Len(); i++ { var exprs = make([]clause.Expression, len(stmt.Schema.PrimaryFields)) var notZero bool @@ -150,10 +150,10 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) { notZero = notZero || !isZero } if notZero { - priamryKeyExprs = append(priamryKeyExprs, clause.And(exprs...)) + primaryKeyExprs = append(primaryKeyExprs, clause.And(exprs...)) } } - stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.Or(priamryKeyExprs...)}}) + stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.Or(primaryKeyExprs...)}}) case reflect.Struct: for _, field := range stmt.Schema.PrimaryFields { if value, isZero := field.ValueOf(stmt.ReflectValue); !isZero { @@ -202,6 +202,8 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) { if field.AutoUpdateTime == schema.UnixNanosecond { set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: now.UnixNano()}) + } else if field.AutoUpdateTime == schema.UnixMillisecond { + set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: now.UnixNano() / 1e6}) } else if field.GORMDataType == schema.Time { set = append(set, clause.Assignment{Column: clause.Column{Name: field.DBName}, Value: now}) } else { @@ -223,6 +225,8 @@ func ConvertToAssignments(stmt *gorm.Statement) (set clause.Set) { if field.AutoUpdateTime > 0 { if field.AutoUpdateTime == schema.UnixNanosecond { value = stmt.DB.NowFunc().UnixNano() + } else if field.AutoUpdateTime == schema.UnixMillisecond { + value = stmt.DB.NowFunc().UnixNano() / 1e6 } else if field.GORMDataType == schema.Time { value = stmt.DB.NowFunc() } else { diff --git a/schema/field.go b/schema/field.go index 6d0fd1cc..4eb95b98 100644 --- a/schema/field.go +++ b/schema/field.go @@ -19,8 +19,9 @@ type DataType string type TimeType int64 const ( - UnixSecond TimeType = 1 - UnixNanosecond TimeType = 2 + UnixSecond TimeType = 1 + UnixMillisecond TimeType = 2 + UnixNanosecond TimeType = 3 ) const ( @@ -233,6 +234,8 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { if v, ok := field.TagSettings["AUTOCREATETIME"]; ok || (field.Name == "CreatedAt" && (field.DataType == Time || field.DataType == Int || field.DataType == Uint)) { if strings.ToUpper(v) == "NANO" { field.AutoCreateTime = UnixNanosecond + } else if strings.ToUpper(v) == "MILLI" { + field.AutoCreateTime = UnixMillisecond } else { field.AutoCreateTime = UnixSecond } @@ -241,6 +244,8 @@ func (schema *Schema) ParseField(fieldStruct reflect.StructField) *Field { if v, ok := field.TagSettings["AUTOUPDATETIME"]; ok || (field.Name == "UpdatedAt" && (field.DataType == Time || field.DataType == Int || field.DataType == Uint)) { if strings.ToUpper(v) == "NANO" { field.AutoUpdateTime = UnixNanosecond + } else if strings.ToUpper(v) == "MILLI" { + field.AutoUpdateTime = UnixMillisecond } else { field.AutoUpdateTime = UnixSecond } @@ -551,6 +556,8 @@ func (field *Field) setupValuerAndSetter() { case time.Time: if field.AutoCreateTime == UnixNanosecond || field.AutoUpdateTime == UnixNanosecond { field.ReflectValueOf(value).SetInt(data.UnixNano()) + } else if field.AutoCreateTime == UnixMillisecond || field.AutoUpdateTime == UnixMillisecond { + field.ReflectValueOf(value).SetInt(data.UnixNano() / 1e6) } else { field.ReflectValueOf(value).SetInt(data.Unix()) } @@ -558,6 +565,8 @@ func (field *Field) setupValuerAndSetter() { if data != nil { if field.AutoCreateTime == UnixNanosecond || field.AutoUpdateTime == UnixNanosecond { field.ReflectValueOf(value).SetInt(data.UnixNano()) + } else if field.AutoCreateTime == UnixMillisecond || field.AutoUpdateTime == UnixMillisecond { + field.ReflectValueOf(value).SetInt(data.UnixNano() / 1e6) } else { field.ReflectValueOf(value).SetInt(data.Unix()) } diff --git a/tests/customize_field_test.go b/tests/customize_field_test.go index 9c6ab948..bf3c78fa 100644 --- a/tests/customize_field_test.go +++ b/tests/customize_field_test.go @@ -61,18 +61,20 @@ func TestCustomColumnAndIgnoredFieldClash(t *testing.T) { func TestCustomizeField(t *testing.T) { type CustomizeFieldStruct struct { gorm.Model - Name string - FieldAllowCreate string `gorm:"<-:create"` - FieldAllowUpdate string `gorm:"<-:update"` - FieldAllowSave string `gorm:"<-"` - FieldAllowSave2 string `gorm:"<-:create,update"` - FieldAllowSave3 string `gorm:"->:false;<-:create"` - FieldReadonly string `gorm:"->"` - FieldIgnore string `gorm:"-"` - AutoUnixCreateTime int64 `gorm:"autocreatetime"` - AutoUnixNanoCreateTime int64 `gorm:"autocreatetime:nano"` - AutoUnixUpdateTime int64 `gorm:"autoupdatetime"` - AutoUnixNanoUpdateTime int64 `gorm:"autoupdatetime:nano"` + Name string + FieldAllowCreate string `gorm:"<-:create"` + FieldAllowUpdate string `gorm:"<-:update"` + FieldAllowSave string `gorm:"<-"` + FieldAllowSave2 string `gorm:"<-:create,update"` + FieldAllowSave3 string `gorm:"->:false;<-:create"` + FieldReadonly string `gorm:"->"` + FieldIgnore string `gorm:"-"` + AutoUnixCreateTime int64 `gorm:"autocreatetime"` + AutoUnixMilliCreateTime int64 `gorm:"autocreatetime:milli"` + AutoUnixNanoCreateTime int64 `gorm:"autocreatetime:nano"` + AutoUnixUpdateTime int64 `gorm:"autoupdatetime"` + AutoUnixMilliUpdateTime int64 `gorm:"autoupdatetime:milli"` + AutoUnixNanoUpdateTime int64 `gorm:"autoupdatetime:nano"` } DB.Migrator().DropTable(&CustomizeFieldStruct{}) @@ -118,6 +120,10 @@ func TestCustomizeField(t *testing.T) { t.Fatalf("invalid create/update unix time: %#v", result) } + if result.AutoUnixMilliCreateTime != result.AutoUnixMilliUpdateTime || result.AutoUnixMilliCreateTime == 0 || result.AutoUnixMilliCreateTime/result.AutoUnixCreateTime < 1e3 { + t.Fatalf("invalid create/update unix milli time: %#v", result) + } + if result.AutoUnixNanoCreateTime != result.AutoUnixNanoUpdateTime || result.AutoUnixNanoCreateTime == 0 || result.AutoUnixNanoCreateTime/result.AutoUnixCreateTime < 1e6 { t.Fatalf("invalid create/update unix nano time: %#v", result) } @@ -163,6 +169,8 @@ func TestCustomizeField(t *testing.T) { createWithDefaultTime := generateStruct("create_with_default_time") createWithDefaultTime.AutoUnixCreateTime = 100 createWithDefaultTime.AutoUnixUpdateTime = 100 + createWithDefaultTime.AutoUnixMilliCreateTime = 100 + createWithDefaultTime.AutoUnixMilliUpdateTime = 100 createWithDefaultTime.AutoUnixNanoCreateTime = 100 createWithDefaultTime.AutoUnixNanoUpdateTime = 100 DB.Create(&createWithDefaultTime) @@ -174,6 +182,10 @@ func TestCustomizeField(t *testing.T) { t.Fatalf("invalid create/update unix time: %#v", createWithDefaultTimeResult) } + if createWithDefaultTimeResult.AutoUnixMilliCreateTime != createWithDefaultTimeResult.AutoUnixMilliUpdateTime || createWithDefaultTimeResult.AutoUnixMilliCreateTime != 100 { + t.Fatalf("invalid create/update unix milli time: %#v", createWithDefaultTimeResult) + } + if createWithDefaultTimeResult.AutoUnixNanoCreateTime != createWithDefaultTimeResult.AutoUnixNanoUpdateTime || createWithDefaultTimeResult.AutoUnixNanoCreateTime != 100 { t.Fatalf("invalid create/update unix nano time: %#v", createWithDefaultTimeResult) }