与==相比,为什么具有相同日期和时间的2个时间结构返回false?

时间:2016-04-14 06:03:06

标签: go time struct date-comparison

我使用time.Time创建了time.Date()。然后我计算1970/1/1 00:00:00.000000000与那个时间之间的纳秒数。

然后我使用纳秒,然后使用time.Time将它们转回time.Unix()

但是,如果我使用==将重构时间与原始时间进行比较,则返回false。如果我减去这两次,结果持续时间为0.如果我使用time.Equal()比较这两次,则返回true。

如果我使用time.Date()使用与第一次相同的值创建另一次,则使用==比较此新时间与原始时间结果为真。

这是演示此内容的代码(Golang Playground):

package main

import (
    "fmt"
    "time"
)

func main() {
    t1 := time.Date(2016, 4, 14, 1, 30, 30, 222000000, time.UTC)


    base := time.Date(1970, 1, 1, 0, 0, 0, 0, t1.Location())
    nsFrom1970 :=t1.Sub(base).Nanoseconds() // Calculate the number of nanoseconds from 1970/1/1 to t1

    t2 := time.Unix(0, nsFrom1970)

    fmt.Println(t1)
    fmt.Println(t2)
    fmt.Println(t1.Sub(t2)) // 0
    fmt.Println(t1 == t2) //false
    fmt.Println(t1.Equal(t2)) //true

    t3 := time.Date(2100, 2, 1, 21, 21, 21, 222000000, time.UTC)
    fmt.Println(t1 == t3) //true
}

为什么重构时间与原始时间相比会返回false?

1 个答案:

答案 0 :(得分:5)

time.Timestruct。当您尝试将它们与==进行比较时,请引用Spec: Comparison operator

  

如果所有字段都具有可比性,则结构值具有可比性。如果相应的非blank字段相等,则两个struct值相等。

因此t1 == t2将比较2个Time结构值的所有字段。 Time结构不仅包含自基准时间以来的第二个和纳秒,它还包含作为指针的位置:*Location,因此==也将比较位置字段。比较指针:

  

指针值具有可比性。如果两个指针值指向同一个变量或两者都具有值nil,则它们相等。不同zero-size变量的指针可能相等也可能不相等。

这就是为什么将时间与==进行比较会得到false结果:即使地址不同,2个地点也可能表示相同的位置,这就是您的情况。

证明这一点:

fmt.Println("Locations:", t1.Location(), t2.Location())
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location())
fmt.Println("Locations equal:", t1.Location() == t2.Location())

输出:

Locations: UTC UTC
Location pointers: 0x1e2100 0x1e6de0
Locations equal: false

time.Time中记录了这一点:

  

请注意,Go ==运算符不仅会比较时刻,还会比较位置。因此,如果没有首先保证为所有值设置了相同的Location,则不应将Time值用作映射或数据库键,这可以通过使用UTC或Local方法来实现。

如果t1t2也包含相同的*Location指针,即使与==运算符进行比较,它们也会相等。这可以通过调用Time.UTC()Time.Local()方法来确保,这些方法返回time.Time值,其中使用相同的位置指针(*Location)。或者使用设置指定位置指针的Time.In()方法(在正确转换后),例如:

t2 = t2.In(t1.Location())
fmt.Println("Locations:", t1.Location(), t2.Location())
fmt.Printf("Location pointers: %p %p\n", t1.Location(), t2.Location())
fmt.Println("Locations equal:", t1.Location() == t2.Location())
fmt.Println(t1 == t2)     // Now true
fmt.Println(t1.Equal(t2)) // Still true

输出:

Locations: UTC UTC
Location pointers: 0x1e2100 0x1e2100
Locations equal: true
true
true

Go Playground上尝试。