英文:
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语言中,我该如何实现这个目标?
英文:
I'm parsing timestamps sent by users. The timestamps are local to a location but the source string doesn't specify it. Server-side I'm looking up the timezone of the location and need to shift the time into that timezone, without changing its display value.
I know I can do this to give me the equivalent time at a different location:
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))
}
This just prints:
2009-11-10T23:00:00Z
2009-11-10T18:00:00-05:00
Which isn't what I want.
I'm trying to find a way of setting the timezone to e.g. America/New_York
, so I should get e.g. 2009-11-10T23:00:00-05:00
, which is the original local time, but with the New York offset applied.
How can I do this in Go?
答案1
得分: 3
混淆的原因在于直观地想到的 API In
会将相同的时间点解释为不同的时区。因此,当你打印它时,显示的结果并不是你想要的。
要将时间戳的时区设置为新的时区,同时保持相同的显示值,你可以使用 time.Date
构造具有与原始时间戳相同值和新位置的新时间戳:
t := time.Date(myTime.Year(), myTime.Month(), myTime.Day(), myTime.Hour(), myTime.Minute(), myTime.Second(), myTime.Nanosecond(), loc)
// 在 playground 中显示为 2009-11-10T23:00:00-05:00
另一种选择是将时间实例设置为新的时区,然后使用 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)
// 处理夏令时转换
if inZoneTime.IsDST() {
inZoneTime = inZoneTime.Add(1*time.Hour)
}
fmt.Println(inZoneTime.Format(time.RFC3339))
// 2009-11-10T23:00:00-05:00
}
要在本地机器上测试今天的夏令时转换(假设你所在的国家没有夏令时,就像我一样),你可以将位置更改为夏令时生效的地方,例如 Australia/Canberra
。
使用没有夏令时的 time.Now()
作为输入,在 Australia/Canberra
时区中,上述程序将打印以下结果:
2021-11-12T13:27:33+01:00
is DST: true
2021-11-12T13:27:33+11:00
Playground: https://play.golang.org/p/5qy2tOcIMwn
英文:
The confusion comes from the fact that the API that intuitively comes to mind In
simply interprets the same point in time as if it were in a different time zone. So when you print it, the display isn't what you want.
To set the time zone to a timestamp while keeping the same display value you can simply construct the new timestamp with time.Date
with the same values as the original timestamp and the new location:
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
<hr>
Another option is to set the time instance to the new time zone, then use Zone()
to get the offset, and then subtract its value in seconds from the localized time.
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
}
To test the DST transition in your local machine today (assuming you are in a non-DST country, as I am) you can change the location to a place where DST is active, e.g. Australia/Canberra
.
With an input of time.Now()
without DST into Australia/Canberra
, the above program prints the following:
2021-11-12T13:27:33+01:00
is DST: true
2021-11-12T13:27:33+11:00
Playground: https://play.golang.org/p/5qy2tOcIMwn
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论