majianyu
4/19/2019 - 7:23 AM

gorm time json

存储到数据库为时间格式,json 序列化与反序列化为时间戳

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"github.com/jinzhu/gorm"
	"strconv"
	"time"
)

type GormBase struct {
	CreatedAt JSONTime   `json:"created_at" gorm:"type:timestamp"`
	UpdateAt  JSONTime   `json:"updated_at" gorm:"type:timestamp"`
	DeletedAt *time.Time `json:"-" gorm:"type:timestamp"`
}

type JSONTime struct {
	Time time.Time
}

/*
*@ date 2019-04-19
*@ author majianyu
*@ description only support second
 */
func (this JSONTime) MarshalJSON() ([]byte, error) {
	return json.Marshal(this.Time.Unix())
}

/*
*@ date 2019-04-19
*@ author majianyu
*@ description support second and millisecond parse
 */
func (this *JSONTime) UnmarshalJSON(b []byte) error {
	str := string(b)
	ts, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return err
	}
	if len(str) == 10 {
		// second
		this.Time = time.Unix(ts, 0)
	} else if len(str) == 13 {
		// millisecond
		this.Time = time.Unix(0, ts*1e6)
	} else {
		return fmt.Errorf("can not convert %s to time", str)
	}
	return nil
}
func (this JSONTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	if this.Time.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return this.Time, nil
}
func (this *JSONTime) Scan(v interface{}) error {
	value, ok := v.(time.Time)
	if ok {
		*this = JSONTime{Time: value}
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)

}

func (g *GormBase) BeforeUpdate(scope *gorm.Scope) error {
	scope.SetColumn("UpdateAt", time.Now())
	return nil
}

func (g *GormBase) BeforeCreate(scope *gorm.Scope) error {
	if g.UpdateAt.Time.Unix() <= 0 {
		scope.SetColumn("UpdateAt", time.Now())
	}

	scope.SetColumn("CreatedAt", time.Now())
	return nil
}

type Report struct {
	tableName struct{}   `sql:"toptutor.report"`
	CourseID  string     `json:"course_id" gorm:"type:uuid"`
	OrderID   string     `json:"order_id" gorm:"type:uuid"`
	Questions []Question `json:"questions" gorm:"type:jsonb"`
	gormstruct.GormBase
}
type Question struct {
	ID         int    `json:"id"`
	Question   string `json:"question"`
	Answer     string `json:"answer"`
	ZhQuestion string `json:"zh_question"`
	ZhAnswer   string `json:"zh_answer"`
}

func (this *Question) Scan(v interface{}) error {
	value, ok := v.([]byte)
	if ok {
		q := Question{}
		err := json.Unmarshal(value, &q)
		if err != nil {
			return fmt.Errorf("can not convert %v to Question", v)
		}
		*this = q
		return nil
	}
	return fmt.Errorf("can not convert %v to Question", v)
}
func (this Question) Value() (driver.Value, error) {
	bytes, err := json.Marshal(this)
	if err != nil {
		return nil, err
	}
	return bytes, nil
}