如何在另一个时区获取等效时间



我正在尝试比较来自不同时区的两个时间,看看一个是否在另一个之前。我将如何在 Go 中执行此操作?

注意:基本上我想要sfTime.Before(nyTime) == true,但我下面的例子会sfTime.Before(nyTime) == false。关于如何实现这一目标的建议会很棒。


例如,在此代码中...

layout := "2006-01-02 15:04 MST"
sfTime, _ := time.Parse(layout, "2017-03-01 12:00 PDT")
nyTime, _ := time.Parse(layout, "2017-03-01 12:00 EDT")
fmt.Printf("Are these times equal? %vn", sfTime.Equal(nyTime))

这将打印:

这些时间相等吗?

游乐场链接在这里。

不直观的是,即使您将它们设置为同一时区,这也只会更改时区,而不会更改HH:mm值。

layout := "2006-01-02 15:04 MST"
sfTime, _ := time.Parse(layout, "2017-03-01 12:00 PDT")
nyTime, _ := time.Parse(layout, "2017-03-01 12:00 EDT")
// Set timezone to UTC
utcLocation, _ := time.LoadLocation("UTC")
sfTime = sfTime.In(utcLocation)
nyTime = nyTime.In(utcLocation)
// Timezones should not be equal, but they are
fmt.Printf("Are these times still equal? %vn", sfTime.Equal(nyTime))
fmt.Printf("The New York Time: %vn", nyTime)

指纹

这些时间还相等吗?

纽约时间: 2017-03-01 12:00:00 +0000 UTC

游乐场链接。

不要使用 Go Playground 进行时间计算。它在具有假时间的沙盒中运行:

关于游乐场

Go Playground是一个在golang.org服务器上运行的Web服务。 该服务接收 Go 程序,编译、链接并运行 在沙盒中编程,然后返回输出。

可以在 操场。

在操场上,时间从 2009-11-10 23:00:00 UTC 开始 (确定此日期的重要性是 读者)。这使得通过给程序来更容易缓存程序 确定性输出。

此外,Go Playground 中的所有时间都使用 UTC 时区。Go Playground 不使用 IANA 时区数据库。

例如,对于此程序,

package main
import (
"fmt"
"time"
)
func main() {
layout := "2006-01-02 15:04 MST"
sfTime, err := time.Parse(layout, "2017-03-01 12:00 PDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(sfTime, sfTime.UTC())
nyTime, err := time.Parse(layout, "2017-03-01 12:00 EDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(nyTime, nyTime.UTC())
fmt.Printf("Are these times equal? %vn", sfTime.Equal(nyTime))
}

Go Playground 的输出是:

2017-03-01 12:00:00 +0000 PDT 2017-03-01 12:00:00 +0000 UTC
2017-03-01 12:00:00 +0000 EDT 2017-03-01 12:00:00 +0000 UTC
Are these times equal? true

为了获得正确的输出,请使用 Go gc 或 gccgo 编译器运行程序:

$ go run equal.go
2017-03-01 12:00:00 +0000 PDT 2017-03-01 12:00:00 +0000 UTC
2017-03-01 11:00:00 -0500 EST 2017-03-01 16:00:00 +0000 UTC
Are these times equal? false

使用 Go gc 或 gccgo 编译器,则sfTime.Before(nyTime) == true

package main
import (
"fmt"
"time"
)
func main() {
layout := "2006-01-02 15:04 MST"
sfTime, err := time.Parse(layout, "2017-03-01 12:00 PDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(sfTime, sfTime.UTC())
nyTime, err := time.Parse(layout, "2017-03-01 12:00 EDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(nyTime, nyTime.UTC())
fmt.Printf("Is the SF time before the NY time? %vn", sfTime.Before(nyTime))
}

输出:

$ go run before.go
2017-03-01 12:00:00 +0000 PDT 2017-03-01 12:00:00 +0000 UTC
2017-03-01 11:00:00 -0500 EST 2017-03-01 16:00:00 +0000 UTC
Is the SF time before the NY time? true

Gotime包比较方法(EqualBeforeAfter)比较UTC值。

我认为这是 play.golang.org 的错误,当我在本地机器上运行它时,它会返回Are these times equal? falseAre these times still equal? false

根据文档,这是预期的行为(返回 false):

相等报告t和你是否代表同一时间时刻。

即使它们在不同的位置,两次也可以相等。

例如,6:00 +0200 CEST 和 4:00 UTC 相等。

您是否尝试过在本地运行它? 游乐场的时间设置为固定的时刻,因此可能与此有关。

您的示例正在按预期工作,在时间上相等。如果你想确保时区也相等,你可以做一些类似t1.Equal(t2) && t1.Location().String() == t2.Location().String()

从文档中添加重点:

每个时间都与它相关联一个位置,在计算时会咨询 时间的演示形式,例如在格式、小时和 年份方法。方法本地、UTC 和 In 返回时间与 具体位置。以这种方式更改位置只会更改 介绍;它不会改变所表示的时间时刻和 因此不会影响前面描述的计算 段落。

因此,据我了解,无论您是time.Parse("... PDT")time.Parse("... EDT")还是sfTime.In(time.UTC)您总是获得相同的时间时刻,自 1970 年以来相同的秒数,因此调用这些时间值的EqualBeforeAfter将返回相同的结果,无论Location如何。

更新:我只想补充所选答案,这不是特定于 Playground 的,原始示例在我的机器上的行为方式相同,如果您查看 peterSO 的 PDT 时间输出,您会发现它仍然被解析为 UTC。这种行为在Parse文档的最后一段中有所描述。(强调我的)

使用区域缩写(如 MST)解析时间时,如果区域 缩写在当前位置具有定义的偏移量,则 使用偏移量。区域缩写"UTC"被识别为 UTC 无论身在何处。如果区域缩写未知,则 Parse 将时间记录为在给定区域的虚构位置 缩写和零偏移量。这个选择意味着这样的时间可以 以相同的布局无损解析和重新格式化,但 表示中使用的确切时刻将因实际而异 区域偏移。为避免此类问题,请首选使用 数字区域偏移量,或使用 ParseInLocation。

下面是使用ParseInLocation和数字时区偏移量的示例:https://play.golang.org/p/vY0muIvk5d

相关内容

  • 没有找到相关文章

最新更新