Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
113 changes: 113 additions & 0 deletions reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,3 +758,116 @@ func ConvertValueToString(val interface{}) string {
}
return jsonutils.Marshal(val).String()
}

func getFloatValue(val interface{}) (float64, error) {
switch v := val.(type) {
case float32:
return float64(v), nil
case float64:
return v, nil
case int:
return float64(v), nil
case int8:
return float64(v), nil
case int16:
return float64(v), nil
case int32:
return float64(v), nil
case int64:
return float64(v), nil
case uint:
return float64(v), nil
case uint8:
return float64(v), nil
case uint16:
return float64(v), nil
case uint32:
return float64(v), nil
case uint64:
return float64(v), nil
case *float32:
return float64(*v), nil
case *float64:
return *v, nil
case *int:
return float64(*v), nil
case *int8:
return float64(*v), nil
case *int16:
return float64(*v), nil
case *int32:
return float64(*v), nil
case *int64:
return float64(*v), nil
case *uint:
return float64(*v), nil
case *uint8:
return float64(*v), nil
case *uint16:
return float64(*v), nil
case *uint32:
return float64(*v), nil
case *uint64:
return float64(*v), nil
case string:
return strconv.ParseFloat(v, 64)
case *string:
return strconv.ParseFloat(*v, 64)
}
return 0, errors.ErrInvalidFormat
}

func getTimeValue(val interface{}) (time.Time, error) {
switch v := val.(type) {
case time.Time:
return v, nil
case *time.Time:
return *v, nil
case string:
return timeutils.ParseTimeStr(v)
case *string:
return timeutils.ParseTimeStr(*v)
}
return time.Time{}, errors.ErrInvalidFormat
}

const MIN_FLOAT_EQUAL_DIFF = float64(0.000001)

func floatEqual(of, nf float64) bool {
if of > nf {
return of < MIN_FLOAT_EQUAL_DIFF+nf
} else if of < nf {
return of+MIN_FLOAT_EQUAL_DIFF > nf
} else {
return true
}
}

const MIN_MICRO_SECOND_EQUAL_DIFF = 1000000

func timeEqual(of, nf time.Time) bool {
ofUnix := of.UnixMicro()
nfUnix := nf.UnixMicro()
if ofUnix == nfUnix {
return true
}
if ofUnix > nfUnix {
return ofUnix < MIN_MICRO_SECOND_EQUAL_DIFF+nfUnix
} else {
return ofUnix+MIN_MICRO_SECOND_EQUAL_DIFF > nfUnix
}
}

func EqualsGrossValue(of, nf interface{}) bool {
ofFloat, ofErr := getFloatValue(of)
nfFloat, nfErr := getFloatValue(nf)
if ofErr == nil && nfErr == nil {
return floatEqual(ofFloat, nfFloat)
}
ofTime, ofErr := getTimeValue(of)
nfTime, nfErr := getTimeValue(nf)
if ofErr == nil && nfErr == nil {
return timeEqual(ofTime, nfTime)
}
return false
}
120 changes: 120 additions & 0 deletions reflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,123 @@ func TestConvertValueToTriState(t *testing.T) {
}
}
}

func TestEqualsGrossValue(t *testing.T) {
cases := []struct {
of interface{}
nf interface{}
want bool
}{
{
of: 1.0,
nf: 1.0,
want: true,
},
{
of: 1.0,
nf: 1.00001,
want: false,
},
{
of: 1.0,
nf: 0.99999,
want: false,
},
{
of: 1.0,
nf: 1.000002,
want: false,
},
{
of: 1.0,
nf: 0.999998,
want: false,
},
{
of: 1.0,
nf: 1.000001,
want: false,
},
{
of: 1.0,
nf: 1.0000011,
want: false,
},
{
of: 1.0,
nf: 1.0000009,
want: true,
},
{
of: 1.0,
nf: 0.999999,
want: false,
},
{
of: 1.0,
nf: 0.9999989,
want: false,
},
{
of: 1.0,
nf: 0.9999991,
want: true,
},
{
of: 1.0,
nf: 1.0000001,
want: true,
},
{
of: 1.0,
nf: 0.9999999,
want: true,
},
{
of: "1.0",
nf: "0.9999999",
want: true,
},
{
of: 1,
nf: "0.9999999",
want: true,
},
{
of: "2025-01-01T00:00:00.000000Z",
nf: "2025-01-01T00:00:00.000001Z",
want: true,
},
{
of: "2025-01-01T00:00:00.000000Z",
nf: "2025-01-01T00:00:00.001001Z",
want: true,
},
{
of: "2025-01-01T00:00:00.000000Z",
nf: "2025-01-01T00:00:01.001000Z",
want: false,
},
{
of: "2025-01-01T00:00:00.999999Z",
nf: "2025-01-01T00:00:01.000000Z",
want: true,
},
{
of: "2025-01-01T00:00:00.999999Z",
nf: "2025-01-01T00:00:01.999000Z",
want: true,
},
{
of: "2025-01-01T00:00:00.999999Z",
nf: "2025-01-01T00:00:01.999999Z",
want: false,
},
}
for _, c := range cases {
got := EqualsGrossValue(c.of, c.nf)
if got != c.want {
t.Errorf("want %v got %v for %v and %v", c.want, got, c.of, c.nf)
}
}
}
3 changes: 3 additions & 0 deletions update.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ func (us *SUpdateSession) SaveUpdateSql(dt interface{}) (*SUpdateSQLResult, erro
if ofJsonStr == nfJsonStr {
continue
}
if EqualsGrossValue(of, nf) {
continue
}
}
if c.IsZero(nf) && c.IsText() {
nf = nil
Expand Down