gorm 處理時間戳


問題

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

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

設置數據庫的 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類型就可以准確進行時間戳變量的讀寫操作。

原理

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

Scanner

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

Valuer

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

unmarshalmarshal 自定義 json 轉換格式

參考

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM