时间的子类型。时间不使用gorm lib创建列

时间:2019-11-25 11:19:06

标签: mysql go go-gorm

我正在尝试将时间戳添加到数据库,并让返回的json带有代表时间戳的数字,而不是时间戳的当前字符串表示形式;本质上是覆盖time.Time的元帅

type JSONTime time.Time

func (j *JSONTime) UnmarshalJSON(data []byte) error {
    if string(data) == "null" {
        return nil
    }
    millis, err := strconv.ParseInt(string(data), 10, 64)
    if err != nil {
        return err
    }
    *j = JSONTime(time.Unix(0, millis*int64(time.Millisecond)))
    return err
}

func (t JSONTime) MarshalJSON() ([]byte, error) {
    //do your serializing here
    stamp := fmt.Sprintf("%d", time.Time(t).Unix()*1000)
    return []byte(stamp), nil
}
type table struct {
    ID        int64    `gorm:"primary_key;auto_increment"json:"id"`
    CreatedAt JSONTime json:"createdAt"`
    UpdatedAt JSONTime json:"updatedAt"`
}

我上面的代码存在的问题只是忽略了数据库中列的创建(创建了其他字段)。我什至手动创建了该列,但gorm也不添加数据。

我相信编组和非编组的工作,但是问题甚至出现在使用它们之前(即,将列添加到db)

我在这里做什么错了?

我正在使用MySQL和库gorm

更新1:

以前,我的表结构如下:

type table struct {
    ID        int64    `gorm:"primary_key;auto_increment"json:"id"`
    CreatedAt time.Time json:"createdAt"`
    UpdatedAt time.Time json:"updatedAt"`
}

这主要是有效的(例如,在数据库上创建列)

在数据库连接方面,我基本上使用:

root:password@tcp(127.0.0.1:3306)/database?parseTime=true

并对我的仓库使用自动迁移:

db,err := // get db connection 
if err != nil {
    panic("Failed to connect to database")
}
db.AutoMigrate(&table{})

1 个答案:

答案 0 :(得分:1)

由于@mkopriva,我终于弄清楚了。

有几个问题:

1- MarshalJSONand UnmarshalJSON仅适用于数据库交互之前和之后

2-结构table的定义没有正确的gorm定义:

type tablestruct {
    ID        int64            `gorm:"primary_key;auto_increment"json:"id"`
    CreatedAt timeLib.JSONTime `gorm:"type:timestamp;default:current_timestamp"json:"createdAt"`
    UpdatedAt timeLib.JSONTime `gorm:"type:timestamp;default:current_timestamp ON update current_timestamp"json:"updatedAt"`
}

3-由于类型JSONTime是新类型,驱动程序不知道如何转换它,因此我们需要覆盖Value

func (jsonTime JSONTime) Value() (driver.Value, error) {
    return time.Time(jsonTime), nil
}

4-最后,我们需要重写Scan才能将数据库值转换为JSONTime

func (jsonTime *JSONTime) Scan(value interface{}) error {
    if value == nil {
        *jsonTime = JSONTime(time.Now())
        return nil
    }
    if readTime, err := driver.DefaultParameterConverter.ConvertValue(value); err == nil {
        if convertedTime, ok := readTime.(time.Time); ok {
            *jsonTime = JSONTime(convertedTime)
            return nil
        }
    }
    return errors.New("failed to scan TIME")
}