Golang:在另一个时区获得相同的时间

时间:2017-03-21 23:25:12

标签: go time timezone

我试图从不同的时区进行两次比较,看看是否有一个在另一个时区之前。我怎么能在golang中做到这一点?

注意:基本上我想要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? %v\n", sfTime.Equal(nyTime))

打印:

  

这些时间相等吗?真

Playground link here

不直观地,即使您将它们设置为相同的时区,也只会更改时区,而不会更改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? %v\n", sfTime.Equal(nyTime))
fmt.Printf("The New York Time: %v\n", nyTime)

打印

  

这些时间是否仍然平等?真的

     

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

Playground link

3 个答案:

答案 0 :(得分:3)

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

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

  

//等于报告t和u是否代表同一时刻。

     

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

     

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

你试过在本地运行吗?操场的时间设置为固定的瞬间,因此它可能与此有关。

答案 1 :(得分:3)

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

  

About the Playground

     

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

     

可以在中运行的程序有一些限制   游乐场。

     

在操场上,时间从2009-11-10 23:00:00 UTC开始   (确定这个日期的重要性是一个练习   读者)。这样可以更轻松地通过提供程序来缓存程序   确定性输出。

此外,Go Playground中的所有时间都使用UTC时区。 Go Playground不使用IANA Time Zone Database

例如,对于此程序,

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? %v\n", 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? %v\n", 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

Go time包比较方法(EqualBeforeAfter)比较UTC值。

答案 2 :(得分:2)

您的示例按预期工作,Equal comparse an instant in time。如果你想确保时区也相同,你可以做t1.Equal(t2) && t1.Location().String() == t2.Location().String()

之类的事情

docs重点强调:

  

每次都有一个位置,在计算时咨询   时间的表示形式,例如格式,小时和   年方法。方法Local,UTC和In返回带有的时间   具体位置。 以这种方式更改位置只会更改   介绍;它不会改变被表示的时刻   因此不会影响前面描述的计算   段落。

所以,据我所知,无论你是time.Parse("... PDT")time.Parse("... EDT")还是sfTime.In(time.UTC),你都会得到相同的时间,自1970年以来的秒数相同因此,无论Equal是什么,在这些时间值上调用BeforeAfterLocation都会返回相同的结果。

更新:我只想添加选择的答案,这不是Playground特定的,原始示例在我的机器上的行为方式相同,如果你看看peterSO' s输出的PDT时间你可以看到它仍然被解析为UTC。 Parse documentation的最后一段中描述了此行为。 (强调我的)

  

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

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