Why do 2 time structures with the same date and time return false compared to ==?

I have time.Time created using time.Date() . Then I calculate the number of nanoseconds between 1970/1/1 00:00:00.000000000 and in the meantime.

Then I will take nanoseconds and return them back to time.Time using time.Unix() .

However, if I compare the recovered time to the original using == , it returns false. If I subtract these 2 times, the resulting duration is 0. If I compare these 2 times using time.Equal() , it will return true.

If I create another time using time.Date() with the same values ​​as the first time, using == to compare this new time, and the original time leads to true.

This is the code that demonstrates this ( 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 } 

Why does the recovered time return false compared to the original time?

+7
struct time go date-comparison
source share
1 answer

time.Time is a struct . When you try to compare them with == , quoting Spec: Comparison operator :

Structure values ​​are comparable if all their fields are comparable. Two structure values ​​are equal if their respective blank fields are equal.

So, t1 == t2 will compare all fields of values ​​of the Time structure. The Time structure contains not only the second and nanosecond from the base time, but also contains the location as a pointer: *Location , therefore == also compares the location fields. Comparison of pointers:

The pointer values ​​are comparable. Two pointer values ​​are equal if they point to the same variable or both are nil . Pointers to various zero-size variables may or may not be equal.

And therefore, comparing time with == gives the result false : 2 locations can indicate the same location, even if their address is different, and this is your case.

To prove this:

 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()) 

Output:

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

This is described in time.Time :

Note that the Go == operator compares not only a point in time, but also a location. Therefore, time values ​​should not be used as map or database keys without first confirming that all values ​​have the same location, which can be achieved using the UTC or Local method.

If t1 and t2 will also contain the same *Location pointer, they will be equal even compared to the == operator. This can be achieved by calling Time.UTC() or Time.Local() , which returns the value time.Time , which uses the same location pointer ( *Location ). Or using the Time.In() method, which sets the specified location pointer (after the correct conversion), for example:

 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 

Output:

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

Try it on the go playground .

+5
source share

All Articles