【发布时间】:2021-07-24 00:28:26
【问题描述】:
我进行 HTTP 调用并从较大的 json 对象中解组 createdTimestamp 字段:
CreatedTimestamp string `json:"createdTimestamp"`
我从 createdTimestamp 的 HTTP 调用中收到的示例是:"2021-07-19T18:51:23"。
它不会自动将其转换为time.Time,因此它真正接受的唯一类型是一个字符串,该类型一直有效,直到 Postgresql 中的类型更改为timestamp with timezone @ 987654327@。和以前一样是without timezone。
我可以为time.Time 对象实现自定义解组方法,甚至可以对其进行格式化,以便输出2021-07-19 18:51:23.+00 之类的内容,但这不会被postgres 接受。
我在尝试插入(通过 GoLang、postgres 驱动程序)时看到的确切错误是:pq: invalid input syntax for type timestamp with time zone: ""
在我尝试使用 db.Exec -> db 类型为 *sql.DB 执行插入后出现此错误。
我正在 Go 中执行此操作,我们将不胜感激!
解组 Json 的代码
type CustomTime struct {
time.Time
}
func (ct *CustomTime) UnmarshalJSON(b []byte) (err error) {
timeToInsertIntoDb := strings.Trim(string(b), "\"")
if timeToInsertIntoDb == "null" {
ct.Time = time.Time{}
return
}
timeToInsertIntoDb = timeToInsertIntoDb + "Z"
ct.Time, err = time.Parse(time.RFC3339, timeToInsertIntoDb)
return
}
对于格式化,它取决于输出,但我确实收到了任何格式的输出。所以如果我这样做,CustomTime.Time.Format(2006-02-01 15:04:05.-07)
我会得到2021-07-19 18:51:23.+00的输出
虽然在这一点上,我什至不确定Timestamp with Timezone 所需的确切格式,但没有太多关于 Golang Postgres 驱动程序的文档。
如果需要更多信息,请询问。我正在尽力整理这个问题。
编辑 1
按照建议,我尝试在 http 调用给出的时间戳上附加一个“Z”。在使用time.RFC3339 进行解析后,我得到了2021-07-19T18:51:23Z 的时间——这仍然失败(给出了上述相同的语法错误)。用这个解析尝试了几种不同的方法。使用它按照我上面所说的方式格式化,并使用它的.String() 方法格式化它,它会给出2021-07-20 18:51:23 +0000 UTC。两者都失败了pq: invalid input syntax for type timestamp with time zone: ""
Unmarshal 期间的代码更改:
func (ct *CustomTime) UnmarshalJSON(b []byte) (err error) {
timeToInsertIntoDb := strings.Trim(string(b), "\"")
if timeToInsertIntoDb == "null" {
ct.Time = time.Time{}
return
}
timeToInsertIntoDb = timeToInsertIntoDb + "Z"
ct.Time, err = time.Parse(time.RFC3339, timeToInsertIntoDb)
return
}
编辑 2
另一件要提的事情是我使用"database/sql" 包和"github.com/lib/pq" 作为数据库连接的Postgres 驱动程序。
这就是错误来自pq 的原因。只是想澄清一下,因为我知道其他人正在使用 gorm。我可以写入其他表,我猜只是这个表有时间戳和时区 Postgres 列。
我正在拨打电话db.Exec("INSERT INTO db (created_timestamp) VALUES ($1)", obj.createdTimestamp.Time
我尝试将它作为字符串传递(这是我之前工作时所做的),但现在这就是我所在的位置,因为人们说最好传递一个 time.Time 变量。
【问题讨论】:
-
如果您能够成功转换为
time.Time,然后将其作为参数传入(请参阅this answer)。请注意,您问题中的示例不一致 -createdTimestamp是否包含时区? -
@Brits,因此不包括时区。上面列出了我在 HTTP 调用中得到的数据,但我得到的数据是 UTC(代表我的现有知识),我一直试图让它存储在那个时区内。我试图传递
time.Time,但这也行不通。请参阅Edit 1——在我刚刚尝试使用不同的time.Parse时,它有更多详细信息。 -
您面临的错误与 postgre 相关。我建议你给我们一个可重现的源代码,包括 sql 查询和执行,就像 Shailesh Suryawanshi 用户在他的帖子中所做的那样。这真的会帮助人们做对。你可能也想分享 http 处理程序代码,我们永远不知道。
-
@thatdevop 如果您能够成功地将
CreatedTimestamp转换为time.Time,那么时间的来源是无关紧要的,您的问题应该是“我如何使用time.Time与一个 Postgresinsert'(并提供一个 minimal reproducible example) -
@Brits 从技术上讲,它现在确实有一个时间戳,因为我在解组期间添加了“Z”,然后将其解析为
RFC3339。它是time.Time类型,我通过在运行db.Exec之前记录类型来确保这一点。它曾经可以工作,实际上我认为数据库没有任何变化。不知道这里发生了什么。
标签: database postgresql datetime go driver