0

GO项目实战 — Gorm格式化时间字段

 1 year ago
source link: https://studygolang.com/articles/35739
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

goshop开源项目的更新

备注:前面项目中用到的代码已经分享到GitHub中去了,并且以后所有项目中会出现的代码都会提交上去,欢迎查阅。感兴趣的可以点个star哦~
https://gitee.com/jobhandsome/goshop/

在使用 gorm 查询时,如果未对时间字段进行处理,结构体内的字段类型咱们使用的是 time.Time

type Model struct {
    ID        int64      `json:"id" gorm:"primary_key"`
    CreatedAt *time.Time `json:"created_at"`
    UpdatedAt *time.Time `json:"updated_at"`
    DeletedAt *time.Time `json:"deleted_at" sql:"index"`
}

这里咱们使用 time.Time 类型在 gorm 进行查询的返回结果,读取到的时间字段往往是这样:"2022-07-03T22:14:02.973528+08:00",带着时区和毫秒。但其实往往这样的格式,不是咱们想要的。

那么问题就来了:

  1. 如果想要 "2022-07-03 22:14:02" 这样的格式,需要怎么处理呢?

  2. 当插入一条数据到对应的表中时,UpdateAt 字段是不赋值的,插入到数据库则会 0001-01-01 00:00:00.000000+00:00,系统赋了⼀个默认值,当不想插⼊默认值时如何处理?

通过上面的分析,咱们能确定两个需求:

  1. 读取到的时间需要是:"2022-07-03 22:14:02" 这样的格式

  2. 当时间字段不赋值时,不插入默认值

解决方法:

定义一个时间类型 struct
type LocalTime time.Time

虽然该数据类型实际类型为 time.Time,但是不具备 time.Time 的内置⽅法,需要重写 MarshalJSON ⽅法来实现数据解析

func (t *LocalTime) MarshalJSON() ([]byte, error) {
    tTime := time.Time(*t)
    return []byte(fmt.Sprintf("\"%v\"", tTime.Format("2006-01-02 15:04:05"))), nil
}

注意:GO的格式化时间的规定时间字符串必须为 2006-01-02 15:04:05 这是GO的诞⽣时间,不能更改为其他时间(这个时间字符串与java的"yyyy-MM-dd HH:mm:ss")同作⽤

time.Time 替换成 LocalTime

type Model struct {
    ID        int64      `json:"id" gorm:"primary_key"`
    CreatedAt *LocalTime `json:"created_at"`
    UpdatedAt *localTime `json:"updated_at"`
    DeletedAt *localTime `json:"deleted_at" sql:"index"`
}

到了这一步就解决了第一个需求读取数据时将将时间数据格式化。

下面来实现第二个需求:
func (t LocalTime) Value() (driver.Value, error) {
    var zeroTime time.Time
    tlt := time.Time(t)
    //判断给定时间是否和默认零时间的时间戳相同
    if tlt.UnixNano() == zeroTime.UnixNano() {
        return nil, nil
    }
    return tlt, nil
}

Value⽅法即在存储时调⽤,将该⽅法的返回值进⾏存储,该⽅法可以实现数据存储前对数据进⾏相关操作。

func (t *LocalTime) Scan(v interface{}) error {
    if value, ok := v.(time.Time); ok {
        *t = LocalTime(value)
        return nil
    }
    return fmt.Errorf("can not convert %v to timestamp", v)
}

Scan⽅法可以实现在数据查询出来之前对数据进⾏相关操作。

到了这一步,咱们就实现了上面需求的功能。 更多功能请持续关注!!!!!

星球地址:https://t.zsxq.com/03MJM7YfI

关注公众号「程序员小乔」

程序员小乔


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK