gorm 處理時間戳

問題

在使用 gorm 的過程當中, 處理時間戳字段時遇到問題。寫時間戳到數據庫時沒法寫入。mysql

經過查閱資料最終問題得以解決,特此總結sql

設置數據庫的 dsn

parseTime = "True" loc = "Local"數據庫

設置自定義 Time 類型

package types

import (
	"database/sql/driver"
	"fmt"
	"time"
)

// Time is alias type for time.Time
type Time time.Time

const (
	timeFormart = "2006-01-02 15:04:05"
	zone        = "Asia/Shanghai"
)

// UnmarshalJSON implements json unmarshal interface.
func (t *Time) UnmarshalJSON(data []byte) (err error) {
	now, err := time.ParseInLocation(`"`+timeFormart+`"`, string(data), time.Local)
	*t = Time(now)
	return
}

// MarshalJSON implements json marshal interface.
func (t Time) 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
}

func (t Time) String() string {
	return time.Time(t).Format(timeFormart)
}

func (t Time) local() time.Time {
	loc, _ := time.LoadLocation(zone)
	return time.Time(t).In(loc)
}

// Value ...
func (t Time) Value() (driver.Value, error) {
	var zeroTime time.Time
	var ti = time.Time(t)
	if ti.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return ti, nil
}

// Scan valueof time.Time 注意是指針類型 method
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)
}

這樣程序中全部的時間值都使用types.Time類型就能夠準確進行時間戳變量的讀寫操做。json

原理

其實就是自定義數據庫數據類型,在 sql driver 中實現自定義類型須要實現 ScannerValuer接口app

Scanner

type Scanner interface {
	Scan(src interface{}) error
}

Valuer

type Valuer interface {
	// Value returns a driver Value.
	Value() (Value, error)
}

unmarshalmarshal 自定義 json 轉換格式spa

參考

https://reading.developerlearning.cn/discuss/2019-06-19-gorm-mysql-timestamp/指針

相關文章
相關標籤/搜索