Go reflect.DeepEqual pitfall - time.Time
I have always been using reflect.DeepEqual()
for checking outputs in functions to be exactly matching what is expected in testings. Recently I encountered a bug that took me a long time to find out what happened.
After carefully assigning my expected object intance, I still couldn’t get DeepEqual()
to return true
for my expected value and returned value.
Here is my struct
I tried spew.Dump() to visually find any mismatch but no result, they are exactly the same. I also tried deep.Equal() to see if other library could give me a hint on what I was wrong but still no result.
It took me a while I finally found that it is the time.Time
object.
They look exactly the same through fmt.Println()
.
Time
Let’s have a look at time.Time
struct first
So there are three fields in time.Time
class, and to dig out more, let’s print them all out.
Since reflect.Value
has defined a String() function and time.Time
will just be printed in usual timestamp format, so I have to print them out one by one.
Result:
The first three lines is from timeA
and the latter three is from timeB
. As you can see, they are identical for the first two fields but different at the last.
If the location field is nil
, it is UTC timezone. My machine is using UTC timezone so Local also represents UTC timezone.
The answer is found and I can finally sleep well at night. My tests failed because time.Time
allows different representations for timezone, not because of other more horrible reasons.
Solution
However, it is very easy to solve.
You just make both of them UTC time specifically.
Hope you enjoy my writing. Feel free to comment.