首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何设置pgx以从DB获取UTC值?

如何设置pgx以从DB获取UTC值?
EN

Stack Overflow用户
提问于 2022-06-27 11:23:02
回答 1查看 406关注 0票数 3

我将恩特Pgx结合使用。

在Postgres中创建的列是:

代码语言:javascript
复制
used_at timestamp with time zone NOT NULL,

Postgres中的值保存时不带时区( UTC):

代码语言:javascript
复制
2022-06-30 22:49:03.970913+00

使用此查询:

代码语言:javascript
复制
show timezone

我得到:

代码语言:javascript
复制
Etc/UTC

但是,从Ent (使用pgx stdlib)中,我得到了以下值:

代码语言:javascript
复制
2022-07-01T00:49:03.970913+02:00

使用pgdriver/pq,我从DB获得UTC值。

如何设置pgx以获得UTC值?

我也尝试在下面的代码中使用这个连接字符串:

代码语言:javascript
复制
import (
    "database/sql"
    _ "github.com/jackc/pgx/v4/stdlib"
)

conn, err := sql.Open("pgx", "postgres://postgres:postgres@localhost/project?sslmode=disable&timezone=UTC")
//handle err

问题还在这里。

我需要一种方法从DB中获取UTC值(这些值存储在DB中).

EN

回答 1

Stack Overflow用户

发布于 2022-06-27 12:24:24

timezone不是有效的https://www.postgresql.org/docs/14/libpq-connect.html#LIBPQ-PARAMKEYWORDS

但是,您可以使用options关键字指定命令行选项,以便在连接开始时发送到服务器。请记住,您需要对其中的值进行百分比编码

如何设置TimeZone的示例

代码语言:javascript
复制
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)

    // sends "-c TimeZone=UTC" to server at connection start
    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)
}
代码语言:javascript
复制
Europe/Prague
UTC

但是,这只会强制执行连接的时区,这似乎对pgx在从数据库中读取时间戳时如何解析时间戳本身没有影响。实际上,它似乎直接或间接地依赖于主机的本地时区。确认您可以将全局time.Local变量更新为UTC并观察差异。

代码语言:javascript
复制
    // ...

    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)

    // explicitly set Local to UTC
    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)
}
代码语言:javascript
复制
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类型。

代码语言:javascript
复制
    // ...

    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)
}
代码语言:javascript
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72771272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档