我应该如何存储 Go 的时间。在波斯特格雷斯的位置?



在Postgres中我存储用户给我的数据:

   Column   |           Type           | Collation | Nullable | Default
------------+--------------------------+-----------+----------+---------
 id         | uuid                     |           | not null |
 value      | numeric                  |           |          |
 date       | timestamp with time zone |           |          |

现在,我介绍了维护生成数据的原始时区的要求。timestamp with timezone已归一化为数据库的时区,而原始时区丢失,因此我必须手动从归一化的时区重新恢复date,然后再将其提供给用户。

大多数解决方案都建议在表中添加额外的列,并将原始时区信息与时间戳一起存储:

   Column   |           Type           | Collation | Nullable | Default
------------+--------------------------+-----------+----------+---------
 id         | uuid                     |           | not null |
 value      | numeric                  |           |          |
 date       | timestamp with time zone |           |          |
 tz         | text                     |           |          |

因此,鉴于我正在使用GO,我应该从time.Time提取哪些信息以存储在tz中,以获取最精确和无缝的修复?

date.Location().String()似乎不正确,因为它可能返回相对的值 Local

以及如何将信息从tz恢复到time.Time

time.LoadLocation(tz)的结果足够好吗?

保存后,我将使用 Time.Zone()获得区域名称并偏移:

func (t Time) Zone() (name string, offset int)

然后,当从数据库中查询这样的时间戳时,您可以使用time.FixedZone()构造time.Location

func FixedZone(name string, offset int) *Location

并使用Time.In()

切换到此位置

谨慎词!这将使您在同一时区域恢复使用"貌似"的时间戳,但是如果您需要对其进行应用程序(例如添加天数(,则结果可能不一样。原因是因为time.FixedZone()返回一个带有固定偏移的时区,例如,对于日光节省一无所知,而您保存的原始时间戳可能具有time.Location,这确实知道这些事情。

这是这样偏差的一个例子。三月份有一个日光节省的一天,所以我们将使用时间戳指向3月1日,并为其添加1个月,从而导致时间戳在节省日光之后。

cet, err := time.LoadLocation("CET")
if err != nil {
    panic(err)
}
t11 := time.Date(2019, time.March, 1, 12, 0, 0, 0, cet)
t12 := t11.AddDate(0, 1, 0)
fmt.Println(t11, t12)
name, offset := t11.Zone()
cet2 := time.FixedZone(name, offset)
t21 := t11.UTC().In(cet2)
t22 := t21.AddDate(0, 1, 0)
fmt.Println(t21, t22)
now := time.Date(2019, time.April, 2, 0, 0, 0, 0, time.UTC)
fmt.Println("Time since t11:", now.Sub(t11))
fmt.Println("Time since t21:", now.Sub(t21))
fmt.Println("Time since t12:", now.Sub(t12))
fmt.Println("Time since t22:", now.Sub(t22))

这将输出(在Go Playground上尝试(:

2019-03-01 12:00:00 +0100 CET 2019-04-01 12:00:00 +0200 CEST
2019-03-01 12:00:00 +0100 CET 2019-04-01 12:00:00 +0100 CET
Time since t11: 757h0m0s
Time since t21: 757h0m0s
Time since t12: 14h0m0s
Time since t22: 13h0m0s

您可以看到,1个月后的输出时间相同,但是区域偏移量不同,因此它们在时间上表示不同的时间(通过显示任意时间的时间差,可以证明这一点(。原件有2小时的偏移,因为它知道我们跳过1个月内发生的日光节省,而"恢复"时间戳的区域不知道这一点,因此结果具有相同的1小时偏移量。在添加后的时间戳中,即使区域名称在现实生活中也会变化:从CETCEST,再一次,还原的时间戳区域也不知道。

更浪费,仍然容易出错,但仍然有效的解决方案还将在ISO 8601格式中存储原始的时间戳,例如2019-05-2T17:24:37+01:00,例如datetext

   Column   |           Type           | Collation | Nullable | Default
------------+--------------------------+-----------+----------+---------
 id         | uuid                     |           | not null |
 value      | numeric                  |           |          |
 date       | timestamp with time zone |           |          |
 datetext   | text                     |           |          |

然后,使用date查询本机时间戳列的强度,然后返回到用户datetext,这是最初发送的确切值。

相关内容

  • 没有找到相关文章

最新更新