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

F21*_*F21 7 time struct go date-comparison

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

然后我拿纳秒并将它们变回time.Time使用状态time.Unix().

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

如果我使用time.Date()与第一次相同的值创建另一个时间,则使用==比较此新时间和原始时间将得到true.

这是演示这个的代码(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
}
Run Code Online (Sandbox Code Playgroud)

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

icz*_*cza 5

time.Time是一个struct.当您尝试与它们进行比较时==,引用Spec:Comparison运算符:

如果所有字段都具有可比性,则结构值可比较.如果相应的非空白字段相等,则两个结构值相等.

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

指针值具有可比性.如果两个指针值指向同一个变量或两者都有值,则它们相等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())
Run Code Online (Sandbox Code Playgroud)

输出:

Locations: UTC UTC
Location pointers: 0x1e2100 0x1e6de0
Locations equal: false
Run Code Online (Sandbox Code Playgroud)

这记录在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
Run Code Online (Sandbox Code Playgroud)

输出:

Locations: UTC UTC
Location pointers: 0x1e2100 0x1e2100
Locations equal: true
true
true
Run Code Online (Sandbox Code Playgroud)

Go Playground尝试一下.