timezone
不是有效的参数关键字。
但是,您可以使用options
关键词,在连接开始时指定要发送到服务器的命令行选项。只需记住需要百分号编码其中的值。
设置TimeZone
的示例:
package main
import (
"context"
"fmt"
"github.com/jackc/pgx/v4"
)
func main() {
ctx := context.Background()
c1, err := pgx.Connect(ctx, "postgres:///?sslmode=disable")
if err != nil {
panic(err)
}
defer c1.Close(ctx)
c2, err := pgx.Connect(ctx, "postgres:///?sslmode=disable&options=-c%20TimeZone%3DUTC")
if err != nil {
panic(err)
}
defer c2.Close(ctx)
var tz1, tz2 string
if err := c1.QueryRow(ctx, "SHOW timezone").Scan(&tz1); err != nil {
panic(err)
}
if err := c2.QueryRow(ctx, "SHOW timezone").Scan(&tz2); err != nil {
panic(err)
}
fmt.Println(tz1)
fmt.Println(tz2)
}
Europe/Prague
UTC
然而,这只是强制连接的时区,对于从数据库中读取的时间戳本身的解析在pgx
中似乎没有影响。实际上,它似乎直接或间接地依赖于主机机器的本地时区。为了确认这一点,您可以将全局变量time.Local
更新为UTC并观察差异。
var t1, t2 time.Time
if err := c1.QueryRow(ctx, "select now()::timestamptz").Scan(&t1); err != nil {
panic(err)
}
if err := c2.QueryRow(ctx, "select now()::timestamptz").Scan(&t2); err != nil {
panic(err)
}
fmt.Println(t1)
fmt.Println(t2)
time.Local = time.UTC
if err := c1.QueryRow(ctx, "select now()::timestamptz").Scan(&t1); err != nil {
panic(err)
}
if err := c2.QueryRow(ctx, "select now()::timestamptz").Scan(&t2); err != nil {
panic(err)
}
fmt.Println(t1)
fmt.Println(t2)
}
Europe/Prague
UTC
2022-06-27 17:18:13.189557 +0200 CEST
2022-06-27 17:18:13.190047 +0200 CEST
2022-06-27 15:18:13.190401 +0000 UTC
2022-06-27 15:18:13.190443 +0000 UTC
出于明显的原因,我会避免上述方法。如果pgx
没有提供一种配置默认位置以解析时间戳的方式,则我能想到的下一个最佳选项是使用自定义的time.Time
类型。
var t1, t2 time.Time
if err := c1.QueryRow(ctx, "select now()::timestamptz").Scan(&t1); err != nil {
panic(err)
}
if err := c2.QueryRow(ctx, "select now()::timestamptz").Scan(&t2); err != nil {
panic(err)
}
fmt.Println(t1)
fmt.Println(t2)
var tt1, tt2 myTime
if err := c1.QueryRow(ctx, "select now()::timestamptz").Scan(&tt1); err != nil {
panic(err)
}
if err := c2.QueryRow(ctx, "select now()::timestamptz").Scan(&tt2); err != nil {
panic(err)
}
fmt.Println(tt1)
fmt.Println(tt2)
}
type myTime struct {
time.Time
}
func (tt *myTime) Scan(src interface{}) error {
if t, ok := src.(time.Time); ok {
tt.Time = t.In(time.UTC)
return nil
}
return fmt.Errorf("myTime: unsupported type %T", src)
}
Europe/Prague
UTC
2022-06-27 17:26:45.94049 +0200 CEST
2022-06-27 17:26:45.940959 +0200 CEST
2022-06-27 15:26:45.941321 +0000 UTC
2022-06-27 15:26:45.941371 +0000 UTC
+00
是一个时区,或者更确切地说是一个偏移量,+00:00。结果在不同的时区中是完全相同的值,可能是客户端格式化的结果。驱动程序不会随意选择东欧偏移量。 - Panagiotis Kanavos