使用 GORM 和 Postgresql 时如何在 Go 中节省数据库时间?
How to save time in the database in Go when using GORM and Postgresql?
我目前正在解析时间字符串并将其保存到数据库 (Postgresql):
event.Time, _ := time.Parse("3:04 PM", "9:00 PM")
// value of event.Time now is: 0000-01-01 21:00:00 +0000 UTC
db.Create(&event)
它给我这个错误:pq: R:"DateTimeParseError" S:"ERROR" C:"22008" M:"date/time field value out of range: \"0000-01-01T21:00:00Z\"" F:"datetime.c" L:"3540"
event.Time
的类型是 time.Time
.
我还尝试将 event.Time
的类型设置为字符串并在 postgresql 中使用时间数据类型:
type Event struct {
Time string `gorm:"type:time
}
但现在我在数据库中获取记录时遇到错误:
sql: Scan error on column index 4: unsupported driver -> Scan pair: time.Time -> *string
进一步调查了这个问题。目前,GORM 不支持任何 Date/Time 类型,除了 timestamp with time zone
这部分代码来自dialect_postgres.go:
case reflect.Struct:
if _, ok := dataValue.Interface().(time.Time); ok {
sqlType = "timestamp with time zone"
}
所以基本上我看到两个选项供您选择:
在 DB 中使用 varchar(10)
,在 Go 中使用 string
,只需将其保存为“9:00 PM”(其中 10 是适合您的数字)
或者在 DB 中使用 timestamp with time zone
,在 Go 中使用 time.Time
,并将日期部分格式化为固定日期 01/01/1970,例如:
time.Parse("2006-01-02 3:04PM", "1970-01-01 9:00PM")
在这种情况下,您必须在演示文稿中省略日期部分,但如果您计划 select 按日期范围,那可能更适合您。
更新 SQL 中的 DATETIME
字段时,Go 字符串必须采用以下格式:time.Now().Format(time.RFC3339)
.
从 Postgres 的角度来看,错误源于没有年份 0000。如果您没有日期,您可以将 1 年添加到转换后的时间戳,给出 '0001-01-01T21:00:00+ 00' 这是一个有效的 Postgres 时间戳。
select '0000-01-01T21:00:00+00'::timestamptz at time zone 'UTC'
ERROR: date/time field value out of range: "0000-01-01T21:00:00+00"
给了他同样的错误。正如 0001-01-01 前 1 天的演示一样:
select '0001-01-01T21:00:00+00'::timestamptz at time zone 'UTC' - interval '1 day' "day_before_1/1/1";
--day_before_1/1/1
--0001-12-31 21:00:00 BC
您可以使用 sql
标签
通过 Gorm 设置任意特定于数据库的类型
type Event struct {
Time time.Time `sql:"type:timestamp without time zone"`
}
我目前正在解析时间字符串并将其保存到数据库 (Postgresql):
event.Time, _ := time.Parse("3:04 PM", "9:00 PM")
// value of event.Time now is: 0000-01-01 21:00:00 +0000 UTC
db.Create(&event)
它给我这个错误:pq: R:"DateTimeParseError" S:"ERROR" C:"22008" M:"date/time field value out of range: \"0000-01-01T21:00:00Z\"" F:"datetime.c" L:"3540"
event.Time
的类型是 time.Time
.
我还尝试将 event.Time
的类型设置为字符串并在 postgresql 中使用时间数据类型:
type Event struct {
Time string `gorm:"type:time
}
但现在我在数据库中获取记录时遇到错误:
sql: Scan error on column index 4: unsupported driver -> Scan pair: time.Time -> *string
进一步调查了这个问题。目前,GORM 不支持任何 Date/Time 类型,除了 timestamp with time zone
这部分代码来自dialect_postgres.go:
case reflect.Struct:
if _, ok := dataValue.Interface().(time.Time); ok {
sqlType = "timestamp with time zone"
}
所以基本上我看到两个选项供您选择:
在 DB 中使用 varchar(10)
,在 Go 中使用 string
,只需将其保存为“9:00 PM”(其中 10 是适合您的数字)
或者在 DB 中使用 timestamp with time zone
,在 Go 中使用 time.Time
,并将日期部分格式化为固定日期 01/01/1970,例如:
time.Parse("2006-01-02 3:04PM", "1970-01-01 9:00PM")
在这种情况下,您必须在演示文稿中省略日期部分,但如果您计划 select 按日期范围,那可能更适合您。
更新 SQL 中的 DATETIME
字段时,Go 字符串必须采用以下格式:time.Now().Format(time.RFC3339)
.
从 Postgres 的角度来看,错误源于没有年份 0000。如果您没有日期,您可以将 1 年添加到转换后的时间戳,给出 '0001-01-01T21:00:00+ 00' 这是一个有效的 Postgres 时间戳。
select '0000-01-01T21:00:00+00'::timestamptz at time zone 'UTC'
ERROR: date/time field value out of range: "0000-01-01T21:00:00+00"
给了他同样的错误。正如 0001-01-01 前 1 天的演示一样:
select '0001-01-01T21:00:00+00'::timestamptz at time zone 'UTC' - interval '1 day' "day_before_1/1/1";
--day_before_1/1/1
--0001-12-31 21:00:00 BC
您可以使用 sql
标签
type Event struct {
Time time.Time `sql:"type:timestamp without time zone"`
}