使用gorm的sqlite中的时间列
time column in sqlite using gorm
我正在尝试从 sqlite 查询对象,但由于类型时间出现此错误:
(sql: Scan error on column index 1: unsupported Scan, storing driver.Value type []uint8 into type *time.Time)
我的结构是:
type Timeline struct {
ID string `json:"id"`
Timestamp *time.Time `json:"timestamp"`
我的数据库是这样的:
CREATE TABLE timelines (id text, timestamp text, ...
样本行之一是:
('Locked in VR', '2018-03-17 10:50:59.548+01:00',...
有什么想法吗?
我应该在结构中加入一些东西吗?
Timestamp *time.Time `json:"timestamp" gorm:"time"`
我对gorm不熟悉,但是不应该定义时间戳类型datetime
而不是text
吗?另外:当您标记 gorm:"time"
时,列名应该是 time
而不是 timestamp
,或者标记 gorm:"timestamp"
。但是你可以省略 gorm 标签。
为简单起见,您可以让 gorm 创建 table:
db, err := gorm.Open("sqlite3", "test.db")
db.CreateTable(&Timeline{})
使用这个就可以搞定:
type Timeline struct {
ID string `json:"id"`
Timestamp *time.Time `json:"timestamp" gorm:"type:datetime"`
}
您甚至可以将 Timestamp
字段的声明类型更改为其他类型,例如 int64
以表示 Unix 时间。然后你可以编写一个扫描器来将日期时间字段读取到 int64 字段中。
type TimeStampUnix int64
type Timeline struct {
ID string `json:"id"`
TimeStamp TimeStampUnix `json:"timestamp" gorm:"type:datetime"`
}
func (t *TimeStampUnix) Scan(src interface{}) error {
switch src.(type) {
case time.Time:
*t = TimeStampUnix(src.(time.Time).Unix())
return nil
case []byte:
// bonus code to read text field of format '2014-12-31 14:21:01-0400'
//
str := string(src.([]byte))
var y, m, d, hr, min, s, tzh, tzm int
var sign rune
_, e := fmt.Sscanf(str, "%d-%d-%d %d:%d:%d%c%d:%d",
&y, &m, &d, &hr, &min, &s, &sign, &tzh, &tzm)
if e != nil {
return e
}
offset := 60 * (tzh*60 + tzm)
if sign == '-' {
offset = -1 * offset
}
loc := time.FixedZone("local-tz", offset)
t1 := time.Date(y, time.Month(m), d, hr, min, s, 0, loc)
*t = TimeStampUnix(t1.Unix())
return nil
default:
return fmt.Errorf("Value '%s' of incompatible type '%T' found", string(src.([]byte)), src)
}
}
我正在尝试从 sqlite 查询对象,但由于类型时间出现此错误:
(sql: Scan error on column index 1: unsupported Scan, storing driver.Value type []uint8 into type *time.Time)
我的结构是:
type Timeline struct {
ID string `json:"id"`
Timestamp *time.Time `json:"timestamp"`
我的数据库是这样的:
CREATE TABLE timelines (id text, timestamp text, ...
样本行之一是:
('Locked in VR', '2018-03-17 10:50:59.548+01:00',...
有什么想法吗? 我应该在结构中加入一些东西吗?
Timestamp *time.Time `json:"timestamp" gorm:"time"`
我对gorm不熟悉,但是不应该定义时间戳类型datetime
而不是text
吗?另外:当您标记 gorm:"time"
时,列名应该是 time
而不是 timestamp
,或者标记 gorm:"timestamp"
。但是你可以省略 gorm 标签。
为简单起见,您可以让 gorm 创建 table:
db, err := gorm.Open("sqlite3", "test.db")
db.CreateTable(&Timeline{})
使用这个就可以搞定:
type Timeline struct {
ID string `json:"id"`
Timestamp *time.Time `json:"timestamp" gorm:"type:datetime"`
}
您甚至可以将 Timestamp
字段的声明类型更改为其他类型,例如 int64
以表示 Unix 时间。然后你可以编写一个扫描器来将日期时间字段读取到 int64 字段中。
type TimeStampUnix int64
type Timeline struct {
ID string `json:"id"`
TimeStamp TimeStampUnix `json:"timestamp" gorm:"type:datetime"`
}
func (t *TimeStampUnix) Scan(src interface{}) error {
switch src.(type) {
case time.Time:
*t = TimeStampUnix(src.(time.Time).Unix())
return nil
case []byte:
// bonus code to read text field of format '2014-12-31 14:21:01-0400'
//
str := string(src.([]byte))
var y, m, d, hr, min, s, tzh, tzm int
var sign rune
_, e := fmt.Sscanf(str, "%d-%d-%d %d:%d:%d%c%d:%d",
&y, &m, &d, &hr, &min, &s, &sign, &tzh, &tzm)
if e != nil {
return e
}
offset := 60 * (tzh*60 + tzm)
if sign == '-' {
offset = -1 * offset
}
loc := time.FixedZone("local-tz", offset)
t1 := time.Date(y, time.Month(m), d, hr, min, s, 0, loc)
*t = TimeStampUnix(t1.Unix())
return nil
default:
return fmt.Errorf("Value '%s' of incompatible type '%T' found", string(src.([]byte)), src)
}
}