使用GORM和Postgresql时如何在Go语言中节省数据库时间?

3

我正在解析一个时间字符串并将其保存到数据库(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:"日期/时间字段值超出范围: \"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

这是因为Go的time.Time实际上是一个日期。目前我没有找到正确使用PostgreSQL Time的方法。如果你不通过它进行查询,我建议使用一个简单的字符串。否则,将其存储为完整的日期。 - Alexey Soshin
1
@AlexeySoshin 我已经尝试将其存储为完整日期,但它给了我这个错误: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" - John Kenn
1
作为一种解决方法,我建议添加一些虚拟日期,例如2099-01-01,这样您就可以在正确考虑这一点的情况下存储时间并进行查询。 - Kamil Gosciminski
4个回答

6

进一步调查了这个问题。目前,GORM没有支持除带有时区的时间戳之外的任何日期/时间类型。

请参阅来自dialect_postgres.go的此代码部分:

case reflect.Struct:
   if _, ok := dataValue.Interface().(time.Time); ok {
      sqlType = "timestamp with time zone"
}

基本上,我认为你有两个选择:

要么在数据库中使用varchar(10),在Go中使用string,并将其简单地保存为“9:00 PM”(其中10是适合你的某个数字)

要么在数据库中使用timestamp with time zone,在Go中使用time.Time,并将日期部分格式化为一个常量日期,例如01/01/1970:

time.Parse("2006-01-02 3:04PM", "1970-01-01 9:00PM")

在这种情况下,您需要在演示文稿中省略日期部分,但如果您计划按日期范围选择,则可能更加适合您。

2

您可以使用Gorm的sql标签设置任意数据库特定类型。

type Event struct {
  Time time.Time `sql:"type:timestamp without time zone"`
}

很遗憾,对于我来说,它在gorm v1.23.5和postgres 14上无法工作。 - chmike

0

在 SQL 中更新 DATETIME 字段时,Go 字符串必须采用以下格式:time.Now().Format(time.RFC3339)


0

从Postgres的角度来看,错误源于没有0000年。如果您不知道日期,您可以将转换后的时间戳加1年,得到有效的Postgres时间戳“0001-01-01T21:00:00+00”。

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 的前一天是:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接