Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

settable time precision for small differences #66

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
settable time precision for small differences
  • Loading branch information
vendelin8 committed Sep 5, 2024
commit 288e73d9dd83ea4b9d4fa2ab0ec9f7d5f72eb4f9
30 changes: 29 additions & 1 deletion deep.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ import (
"log"
"reflect"
"strings"
"time"
)

var (
// FloatPrecision is the number of decimal places to round float values
// to when comparing.
FloatPrecision = 10

// TimePrecision is a precision used for time.Time.Truncate(), if it is non-zero.
TimePrecision time.Duration

// MaxDiff specifies the maximum number of differences to return.
MaxDiff = 10

Expand Down Expand Up @@ -79,7 +83,11 @@ type cmp struct {
flag map[byte]bool
}

var errorType = reflect.TypeOf((*error)(nil)).Elem()
var (
errorType = reflect.TypeOf((*error)(nil)).Elem()
timeType = reflect.TypeOf(time.Time{})
durationType = reflect.TypeOf(time.Nanosecond)
)

// Equal compares variables a and b, recursing into their structure up to
// MaxDepth levels deep (if greater than zero), and returns a list of differences,
Expand Down Expand Up @@ -203,6 +211,23 @@ func (c *cmp) equals(a, b reflect.Value, level int) {
return
}

fixTimePrecision := func() {
if TimePrecision > 0 {
switch aType {
case timeType, durationType:
aFunc := a.MethodByName("Truncate")
bFunc := a.MethodByName("Truncate")

if aFunc.CanInterface() && bFunc.CanInterface() {
precision := reflect.ValueOf(TimePrecision)

a = aFunc.Call([]reflect.Value{precision})[0]
b = bFunc.Call([]reflect.Value{precision})[0]
}
}
}
}

switch aKind {

/////////////////////////////////////////////////////////////////////
Expand All @@ -221,6 +246,8 @@ func (c *cmp) equals(a, b reflect.Value, level int) {
Iterate through the fields (FirstName, LastName), recurse into their values.
*/

fixTimePrecision()

// Types with an Equal() method, like time.Time, only if struct field
// is exported (CanInterface)
if eqFunc := a.MethodByName("Equal"); eqFunc.IsValid() && eqFunc.CanInterface() {
Expand Down Expand Up @@ -439,6 +466,7 @@ func (c *cmp) equals(a, b reflect.Value, level int) {
c.saveDiff(a.Bool(), b.Bool())
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
fixTimePrecision()
if a.Int() != b.Int() {
c.saveDiff(a.Int(), b.Int())
}
Expand Down