gorm 的time.Time 显示特别不直观,总是展示什么带T的字符。
因而重写了 time.Time 的输入输出接口。
建议采用第一种方法,该方法在前端返回字符串,后端储存如2022-07-23 01:09:27 的日期字段,比较直观。
方法一,采用潜在类型:
type Time time.Time
// UnmarshalJSON 1. 为 Xtime 重写 UnmarshalJSON 方法,在此方法中实现自定义格式的转换;
func (t *Time) UnmarshalJSON(data []byte) (err error) {
num, err := strconv.Atoi(string(data))
if err != nil {
return err
}
*t = Time(time.Unix(int64(num), 0))
return
}
// MarshalJSON 2. 为 Xtime 重写 MarshaJSON 方法,在此方法中实现自定义格式的转换;
func (t Time) MarshalJSON() ([]byte, error) {
return ([]byte)(strconv.FormatInt(time.Time(t).Unix(), 10)), nil
}
// Value 3. 为 Time 实现 Value 方法,写入数据库时会调用该方法将自定义时间类型转换并写入数据库;
func (t Time) Value() (driver.Value, error) {
var zeroTime time.Time
if time.Time(t).Unix() == zeroTime.UnixNano() {
return nil, nil
}
return time.Time(t), nil
}
// Scan 4. 为 Time 实现 Scan 方法,读取数据库时会调用该方法将时间数据转换成自定义时间类型;
func (t *Time) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = Time(value)
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
方法二,创建匿名继承类:
/*-----------------------------------------*/
/*--- XTime 时间设定 -----------*/
type XTime struct {
time.Time
}
var ExTimeUnmarshalTimeFormat = "2006-01-02 15:04:05"
var ExTimeMarshalTimeFormat = "2006-01-02 15:04:05"
func (t XTime) UnmarshalTimeFormat() string {
return ExTimeUnmarshalTimeFormat
}
func (t XTime) MarshalTimeFormat() string {
return ExTimeMarshalTimeFormat
}
// UnmarshalJSON 1. 为 Xtime 重写 UnmarshalJSON 方法,在此方法中实现自定义格式的转换;
func (t *XTime) UnmarshalJSON(b []byte) error {
b = bytes.Trim(b, "") // 此除需要去掉传入的数据的两端的 ""
ext, err := time.Parse(t.UnmarshalTimeFormat(), string(b))
if err != nil {
// do something
}
*t = XTime{ext}
return nil
}
// MarshalJSON 2. 为 Xtime 重写 MarshaJSON 方法,在此方法中实现自定义格式的转换;
func (t XTime) MarshalJSON() ([]byte, error) {
output := fmt.Sprintf("%s", t.Format("2006-01-02 15:04:05"))
return []byte(output), nil
}
// Value 3. 为 Xtime 实现 Value 方法,写入数据库时会调用该方法将自定义时间类型转换并写入数据库;
func (t XTime) Value() (driver.Value, error) {
var zeroTime time.Time
if t.Time.UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return t.Time, nil
}
// Scan 4. 为 Xtime 实现 Scan 方法,读取数据库时会调用该方法将时间数据转换成自定义时间类型;
func (t *XTime) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = XTime{Time: value}
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
/*--- XTime 时间设定结束 ------------*/
/*-----------------------------------------*/
重写的BaseModel如下:
package baseModel
import (
"database/sql/driver"
"encoding/json"
"fmt"
"gorm.io/gorm"
"strconv"
"time"
)
type BaseModel struct {
ID uint `json:"ID" gorm:"primarykey"`
CreatedAt Time `json:"CreatedAt" gorm:"column:createdat"`
UpdatedAt Time `json:"UpdatedAt" gorm:"column:updatedat"`
DeletedAt gorm.DeletedAt `json:"DeletedAt" gorm:"column:deletedat"`
}
type Time time.Time
// UnmarshalJSON 1. 为 Time 重写 UnmarshalJSON 方法,在此方法中实现自定义格式的转换;
func (t *Time) UnmarshalJSON(data []byte) (err error) {
num, err := strconv.Atoi(string(data))
if err != nil {
return err
}
*t = Time(time.Unix(int64(num), 0))
return
}
// MarshalJSON 2. 为 Time 重写 MarshaJSON 方法,在此方法中实现自定义格式的转换;
func (t Time) MarshalJSON() ([]byte, error) {
return ([]byte)(strconv.FormatInt(time.Time(t).Unix(), 10)), nil
}
// Value 3. 为 Time 实现 Value 方法,写入数据库时会调用该方法将自定义时间类型转换并写入数据库;
func (t Time) Value() (driver.Value, error) {
var zeroTime time.Time
if time.Time(t).Unix() == zeroTime.UnixNano() {
return nil, nil
}
return time.Time(t), nil
}
// Scan 4. 为 Time 实现 Scan 方法,读取数据库时会调用该方法将时间数据转换成自定义时间类型;
func (t *Time) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = Time(value)
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
const (
timeFormart = "2006-01-02 15:04:05"
)
func (t Time) String() string {
b := make([]byte, 0, len(timeFormart))
b = time.Time(t).AppendFormat(b, timeFormart)
return string(b)
}
/*-----------------------------------------*/
/*--- []uint 设定 -----------*/
type UintArray []uint
// 入库。实现 driver.Valuer 接口,Value 返回 json value
func (j UintArray) Value() (driver.Value, error) {
if len(j) == 0 {
return "", nil
}
marshal, err := json.Marshal(j)
if err != nil {
return "", nil
}
return string(marshal), nil
}
// 出库。实现 sql.Scanner 接口,Scan 将 value 扫描至 Jsonb
func (j *UintArray) Scan(value interface{}) error {
uintBytes, ok := value.([]byte)
if !ok || len(uintBytes) == 0 {
return nil
}
result := UintArray{}
err := json.Unmarshal(uintBytes, &result)
*j = result
return err
}
/*--- []unit 时间设定结束 ------------*/
/*-----------------------------------------*/