文章目录[隐藏]
问题
在使用 gorm 的过程中, 处理时间戳字段时遇到问题。写时间戳到数据库时无法写入。
通过查阅资料最终问题得以解决,特此总结
设置数据库的 dsn
parseTime = "True"
loc = "Local"
设置自定义 Time 类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
package base import ( "errors" "fmt" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsontype" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" "time" ) type JsonTime time.Time const ( timeFormart = "2006-01-02 15:04:05" ) //实现json反序列化,从传递的字符串中解析成时间对象 func (t *JsonTime) UnmarshalJSON(data []byte) (err error) { now, err := time.ParseInLocation(`"`+timeFormart+`"`, string(data), time.Local) *t = JsonTime(now) return } //实现json序列化,将时间转换成字符串byte数组 func (t JsonTime) MarshalJSON() ([]byte, error) { b := make([]byte, 0, len(timeFormart)+2) b = append(b, '"') b = time.Time(t).AppendFormat(b, timeFormart) b = append(b, '"') return b, nil } //mongodb是存储bson格式,因此需要实现序列化bsonvalue(这里不能实现MarshalBSON,MarshalBSON是处理Document的),将时间转换成mongodb能识别的primitive.DateTime func (t *JsonTime) MarshalBSONValue() (bsontype.Type, []byte, error) { targetTime := primitive.NewDateTimeFromTime(time.Time(*t)) return bson.MarshalValue(targetTime) } //实现bson反序列化,从mongodb中读取数据转换成time.Time格式,这里用到了bsoncore中的方法读取数据转换成datetime然后再转换成time.Time func (t *JsonTime) UnmarshalBSONValue(t2 bsontype.Type, data []byte) error { v, _, valid := bsoncore.ReadValue(data, t2) if valid == false { return errors.New(fmt.Sprintf("%s, %s, %s", "读取数据失败:", t2, data)) } *t = JsonTime(v.Time()) return nil } |
这样程序中所有的时间值都使用base.JsonTime
类型就可以准确进行时间戳变量的读写操作。
1 2 3 4 5 6 |
type Order struct { ID uint `json:"id" gorm:"primarykey"` CreatedAt base.JsonTime `json:"created_at"` UpdatedAt base.JsonTime `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` } |
原理
其实就是自定义数据库数据类型,在 sql driver 中实现自定义类型需要实现 Scanner
和Valuer
接口
Scanner
1 2 3 |
type Scanner interface { Scan(src interface{}) error } |
Valuer
1 2 3 4 |
type Valuer interface { // Value returns a driver Value. Value() (Value, error) } |
unmarshal
和marshal
自定义 json 转换格式
参考
gorm 处理时间戳
https://reading.developerlearning.cn/discuss/2019-06-19-gorm-mysql-timestamp/