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

标签 go time struct date-comparison

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

然后我使用 time.Unix() 获取纳秒并将它们变回 time.Time

但是,如果我使用 == 将重构时间与原始时间进行比较,它会返回 false。如果我减去这 2 次,得到的持续时间为 0。如果我使用 time.Equal() 比较这 2 次,它返回 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?

最佳答案

time.Time是一个结构。当您尝试将它们与 == 进行比较时,引用自 Spec: Comparison operator :

Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.

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

Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil. Pointers to distinct zero-size variables may or may not be equal.

这就是为什么用 == 比较时间会得到 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 中:

Note that the Go == operator compares not just the time instant but also the Location. Therefore, Time values should not be used as map or database keys without first guaranteeing that the identical Location has been set for all values, which can be achieved through use of the UTC or Local method.

如果 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 上试试.

关于go - 为什么与 == 相比,具有相同日期和时间的 2 个时间结构返回 false?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36614921/

相关文章:

java - java.time.Duration 的 Android 等价物是什么?

assembly - 显示 assembly 时间

C 结构运算符

c++ - 通过一个套接字发送和接收两个结构

go - 如何使用 context.Context 与 tcp 连接读取

go - panic : runtime error: invalid memory address or nil pointer dereference only on the GAE

go - 如何使用 gorm 的反射类型来泛化 api 函数

go - 当一个是 native 类型时,为什么 golang 禁止分配给相同的底层类型?

java - 未指定偏移量如何解析?

Swift 错误 - 在类型上使用实例成员