我试图从不同的时区进行两次比较,看看是否有一个在另一个时区之前。我怎么能在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))
打印:
这些时间相等吗?真
不直观地,即使您将它们设置为相同的时区,也只会更改时区,而不会更改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
答案 0 :(得分:3)
我认为这是play.golang.org的一个错误,当我在本地计算机上运行它时会返回Are these times equal? false
和Are these times still equal? false
。
根据文档,这是预期的行为(返回false):
//等于报告t和u是否代表同一时刻。
//即使它们位于不同的位置,两次也可以相等。
//例如,6:00 + 0200 CEST和4:00 UTC是相等的。
你试过在本地运行吗?操场的时间设置为固定的瞬间,因此它可能与此有关。
答案 1 :(得分:3)
不要使用Go 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
包比较方法(Equal
,Before
和After
)比较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
是什么,在这些时间值上调用Before
,After
和Location
都会返回相同的结果。
更新:我只想添加选择的答案,这不是Playground特定的,原始示例在我的机器上的行为方式相同,如果你看看peterSO' s输出的PDT时间你可以看到它仍然被解析为UTC。 Parse
documentation的最后一段中描述了此行为。 (强调我的)
使用区域缩写(如MST)解析时间时,如果是区域 缩写在当前位置具有已定义的偏移,然后是 使用偏移量。区域缩写" UTC"被识别为UTC 无论位置如何。 如果区域缩写未知,则解析 将时间记录在给定区域的捏造位置 缩写和零偏移。这个选择意味着这样的时间可以 无损地解析和重新格式化相同的布局,但是 表示中使用的确切时刻将因实际而异 区域偏移。为避免此类问题,更喜欢使用a的时间布局 数字区域偏移,或使用ParseInLocation。
以下是使用ParseInLocation
和数字时区偏移的示例:https://play.golang.org/p/vY0muIvk5d