代码之家  ›  专栏  ›  技术社区  ›  tiagodll

使用gorm的sqlite中的时间列

  •  3
  • tiagodll  · 技术社区  · 6 年前

    我试图从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"`
    
    2 回复  |  直到 6 年前
        1
  •  5
  •   mbuechmann    6 年前

    我不熟悉gorm,但不应该定义类型的时间戳 datetime 而不是 text ?另外:标记时 gorm:"time" 列名应为 time 而不是 timestamp ,或标签 gorm:"timestamp" .但你可以省略gorm标签。

    为了简单起见,您可以让gorm创建表:

    db, err := gorm.Open("sqlite3", "test.db")
    db.CreateTable(&Timeline{})
    
        2
  •  3
  •   CppNoob    6 年前

    使用它可以解决以下问题:

    type Timeline struct {
        ID        string     `json:"id"`
        Timestamp *time.Time `json:"timestamp" gorm:"type:datetime"`
    }
    

    您甚至可以更改 Timestamp 比如说,字段 int64 表示Unix时代。然后,您可以编写一个扫描器,将datetime字段读入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)
        }
    }