r3labs / diff

A library for diffing golang structures
Mozilla Public License 2.0
895 stars 84 forks source link

compare time in millisecond level because of the accuracy lose caused… #20

Closed tianhongw closed 4 years ago

tianhongw commented 4 years ago

var (
    now = time.Now()
)

type A struct {
    CreateTime time.Time `json:"createTime" diff:"createTime"`
}

func main() {
    a1 := A{
        CreateTime: now,
    }

    a2 := A{
        CreateTime: now,
    }

    data, err := json.Marshal(a2)
    if err != nil {
        log.Fatal(err)
    }

    json.Unmarshal(data, &a2)

    changelog, err := diff.Diff(a1, a2)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%+v\n", changelog)
}

output:

[{Type:update Path:[createTime] From:2019-11-20 10:37:01.468951807 +0800 CST m=+0.000059503 To:2019-11-20 10:37:01.468951807 +
0800 CST}]

Marshal and umarshal time type will lose accuracy. Compare time in millisecond may be enough.

purehyperbole commented 4 years ago

Hey @Trytwice. Thanks for raising the issue. I've tried your branch on my system and it looks as if the same unexpected result is happening.

The json marshal is converting that time field into an RFC3339Nano formatted string, which also introduces issues with time zones changing from the original. (on my system, it was comparing GMT 0 with UTC 0, which are actually the same thing)

I think the best way to handle this is to diff to unix nano time. That way, no precision is lost and the comparison is standardised. I've left a comment with the suggested change.