在 Golang 中编组/取消编组时间对象时意外失败



由于几个字符,取消编组时间对象的编组失败

测试

声明以下内容:

// values
now := time.Now()
timeToJSON, _ := json.Marshal(now)
var obj time.Time
json.Unmarshal(timeToJSON, &obj)

然后执行以下测试逻辑:

if !assert.Equal(t,
now.String(),
obj.String()) {
t.FailNow()
}

预期

要通过的测试,并且两个对象要相等

实际

它失败:

--- FAIL: TestFromJSON (0.00s)
D:dev2017GOsrcezsoftapiserver_sdkmodeldeletedeleteModel_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.

注意

我注意到,在检查输出时,不知何故,一些m=+[blah]被附加到预期/实际。

但是,我不知道为什么,略读 RFC 3339 并没有给我任何提示。

根据文档,m值是单调时钟值,可以使用Truncate将其删除以进行比较,而不是出于计时目的。m字段不匹配,因为它在 JSON 中省略了,它仅由time.Now()生成。

尝试如下:

// values
now := time.Now().Truncate(0)  // Truncate to remove monotonic clock portion
timeToJSON, _ := json.Marshal(now)
var obj time.Time
json.Unmarshal(timeToJSON, &obj)

添加了单调时钟偏移,以便准确安排跨越挂钟变化的持续时间(例如NTP更新,DST变化或闰秒/拖尾(。

time.String()不是测试时间值的可靠方法(除非您也关心单调时钟值(。 从文档中(强调添加(:

func (时间( 字符串

func (t Time) String() string

字符串返回使用格式字符串格式化的时间

"2006-01-02 15:04:05.999999999 -0700 MST"

如果时间具有单调时钟读数,则返回的字符串包括最后一个字段"m=±",其中值是格式化为十进制秒数的单调时钟读数。

返回的字符串用于调试;对于稳定的序列化表示形式,请使用带有显式格式字符串的 t.MarshalText、t.MarshalBinary 或 t.Format。

对于您的用例,最好使用time.MarshalText()的输出而不是time.String()

expected, _ := now.MarshalText()
actual, _ := obj.MarshalText()
if !assert.Equal(string(expected), string(actual)) ...

最新更新