如何在不重新解释的情况下将时区设置为现有时间戳?
How to set a timezone to an existing timestamp without reinterpreting it?
我正在解析用户发送的时间戳。时间戳是某个位置的本地时间戳,但源字符串未指定它。服务器端我正在查找位置的时区,需要将时间转移到该时区,而不更改其显示值。
我知道我可以这样做,以便在不同的位置给我相同的时间:
package main
import (
"fmt"
"time"
)
func main() {
myTime := time.Now()
fmt.Println(myTime.Format(time.RFC3339))
loc, err := time.LoadLocation("America/New_York")
if err != nil {
panic(err)
}
fmt.Println(myTime.In(loc).Format(time.RFC3339))
}
这只是打印:
2009-11-10T23:00:00Z
2009-11-10T18:00:00-05:00
这不是我想要的。
我正在尝试找到一种将时区设置为例如America/New_York
,所以我应该得到例如2009-11-10T23:00:00-05:00
,这是原始当地时间,但应用了纽约时差。
我如何在 Go 中执行此操作?
混淆来自这样一个事实,即直观地想到 In
的 API 只是将同一时间点解释为好像它处于不同的时区。所以当你打印它时,显示不是你想要的。
要将时区设置为时间戳,同时保持相同的显示值,您只需使用 time.Date
构造新时间戳,其值与原始时间戳和新位置相同:
t := time.Date(myTime.Year(), myTime.Month(), myTime.Day(), myTime.Hour(), myTime.Minute(), myTime.Second(), myTime.Nanosecond(), loc)
// 2009-11-10T23:00:00-05:00 in the playground
另一种选择是将时间实例设置为新时区,然后使用Zone()
获取偏移量,然后从本地化时间中减去它的秒数。
package main
import (
"fmt"
"time"
)
func main() {
myTime := time.Now()
fmt.Println(myTime.Format(time.RFC3339))
loc, err := time.LoadLocation("America/New_York")
if err != nil {
panic(err)
}
locTime := myTime.In(loc)
_, zoneOffset := locTime.Zone()
inZoneTime := locTime.Add(-time.Duration(zoneOffset) * time.Second)
// handle DST transitions
if inZoneTime.IsDST() {
inZoneTime = inZoneTime.Add(1*time.Hour)
}
fmt.Println(inZoneTime.Format(time.RFC3339))
// 2009-11-10T23:00:00-05:00
}
今天要在您的本地计算机上测试 DST 转换(假设您像我一样在非 DST 国家/地区),您可以将位置更改为 DST 处于活动状态的地方,例如Australia/Canberra
.
将不带 DST 的 time.Now()
输入到 Australia/Canberra
,上面的程序打印以下内容:
2021-11-12T13:27:33+01:00
is DST: true
2021-11-12T13:27:33+11:00
我正在解析用户发送的时间戳。时间戳是某个位置的本地时间戳,但源字符串未指定它。服务器端我正在查找位置的时区,需要将时间转移到该时区,而不更改其显示值。
我知道我可以这样做,以便在不同的位置给我相同的时间:
package main
import (
"fmt"
"time"
)
func main() {
myTime := time.Now()
fmt.Println(myTime.Format(time.RFC3339))
loc, err := time.LoadLocation("America/New_York")
if err != nil {
panic(err)
}
fmt.Println(myTime.In(loc).Format(time.RFC3339))
}
这只是打印:
2009-11-10T23:00:00Z
2009-11-10T18:00:00-05:00
这不是我想要的。
我正在尝试找到一种将时区设置为例如America/New_York
,所以我应该得到例如2009-11-10T23:00:00-05:00
,这是原始当地时间,但应用了纽约时差。
我如何在 Go 中执行此操作?
混淆来自这样一个事实,即直观地想到 In
的 API 只是将同一时间点解释为好像它处于不同的时区。所以当你打印它时,显示不是你想要的。
要将时区设置为时间戳,同时保持相同的显示值,您只需使用 time.Date
构造新时间戳,其值与原始时间戳和新位置相同:
t := time.Date(myTime.Year(), myTime.Month(), myTime.Day(), myTime.Hour(), myTime.Minute(), myTime.Second(), myTime.Nanosecond(), loc)
// 2009-11-10T23:00:00-05:00 in the playground
另一种选择是将时间实例设置为新时区,然后使用Zone()
获取偏移量,然后从本地化时间中减去它的秒数。
package main
import (
"fmt"
"time"
)
func main() {
myTime := time.Now()
fmt.Println(myTime.Format(time.RFC3339))
loc, err := time.LoadLocation("America/New_York")
if err != nil {
panic(err)
}
locTime := myTime.In(loc)
_, zoneOffset := locTime.Zone()
inZoneTime := locTime.Add(-time.Duration(zoneOffset) * time.Second)
// handle DST transitions
if inZoneTime.IsDST() {
inZoneTime = inZoneTime.Add(1*time.Hour)
}
fmt.Println(inZoneTime.Format(time.RFC3339))
// 2009-11-10T23:00:00-05:00
}
今天要在您的本地计算机上测试 DST 转换(假设您像我一样在非 DST 国家/地区),您可以将位置更改为 DST 处于活动状态的地方,例如Australia/Canberra
.
将不带 DST 的 time.Now()
输入到 Australia/Canberra
,上面的程序打印以下内容:
2021-11-12T13:27:33+01:00
is DST: true
2021-11-12T13:27:33+11:00