小编典典

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

go

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

然后,我花了十亿分之一秒,然后将它们重新变成了time.Timeuse time.Unix()

但是,如果我使用来比较重构时间和原始时间==,则返回false。如果我减去这2次,则得到的持续时间为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
}

为什么重组时间与原始时间相比返回假?


阅读 358

收藏
2020-07-02

共1个答案

小编典典

time.Time是一个struct。当您尝试将它们与进行比较时==,请引用“
规范:比较运算符”

如果结构的所有字段都是可比较的,则它们的值是可比较的。如果两个结构值对应的非空白字段相等,则它们相等。

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

指针值是可比较的。如果两个指针值指向同一个变量或都具有value,则它们相等nil。指向不同零大小变量的指针可以相等或可以不相等。

这就是为什么将时间与进行比较从而==得出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
==运算符不仅会比较时间瞬间,还会比较位置。因此,在不首先确保已为所有值设置相同的位置的情况下,不应将时间值用作地图或数据库键,这可以通过使用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上尝试一下。

2020-07-02