Unmarshalling a marshalled time object is failing, because of a few characters
Test
declare the following:
// values
now := time.Now()
timeToJSON, _ := json.Marshal(now)
var obj time.Time
json.Unmarshal(timeToJSON, &obj)
then do the following test logic:
if !assert.Equal(t,
now.String(),
obj.String()) {
t.FailNow()
}
Expected
the test to pass, and the two objects to be equal
Actual
It fails:
--- FAIL: TestFromJSON (0.00s)
D:\dev2017\GO\src\ezsoft\apiserver_sdk\model\delete\deleteModel_test.go:94:
Error Trace: deleteModel_test.go:94
Error: Not equal:
expected: "2018-09-04 10:36:18.3627338 -0400 EDT m=+0.014000801"
actual : "2018-09-04 10:36:18.3627338 -0400 EDT"
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-2018-09-04 10:36:18.3627338 -0400 EDT m=+0.014000801
+2018-09-04 10:36:18.3627338 -0400 EDT
Test: TestFromJSON
FAIL
FAIL ezsoft/apiserver_sdk/model/delete 1.336s
Error: Tests failed.
NOTE
I notice that, upon inspecting the output, that, somehow, some m=+[blah]
is being appended to expected/actual.
I don't know why, however, and skimming RFC 3339 doesn't give me any hints why.
Per the documentation, the m
value is the monotonic clock value, which can be removed using Truncate
for comparisons not for the purpose of timing. The m
field does not match because it is omitted from JSON, it is only generated by time.Now()
.
Try like so:
// values
now := time.Now().Truncate(0) // Truncate to remove monotonic clock portion
timeToJSON, _ := json.Marshal(now)
var obj time.Time
json.Unmarshal(timeToJSON, &obj)
The monotonic clock offset was added in order to allow for accurate timing of durations which span a wall clock change (e.g. NTP update, DST change, or leap second/smear).
time.String()
is not a reliable way to testing a time's value (unless you care about the monotonic clock value, as well). From the docs (Emphasis added):
func (Time) String
func (t Time) String() string
String returns the time formatted using the format string
"2006-01-02 15:04:05.999999999 -0700 MST"
If the time has a monotonic clock reading, the returned string includes a final field "m=±", where value is the monotonic clock reading formatted as a decimal number of seconds.
The returned string is meant for debugging; for a stable serialized representation, use t.MarshalText, t.MarshalBinary, or t.Format with an explicit format string.
For your use-case, it would be better to use the output of time.MarshalText()
instead of time.String()
:
expected, _ := now.MarshalText()
actual, _ := obj.MarshalText()
if !assert.Equal(string(expected), string(actual)) ...