github.com/thiagoyeds/go-cloud@v0.26.0/docstore/driver/compare.go (about)

     1  // Copyright 2019 The Go Cloud Development Kit Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Useful comparison functions.
    16  
    17  package driver
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"reflect"
    23  	"time"
    24  )
    25  
    26  // CompareTimes returns -1, 1 or 0 depending on whether t1 is before, after or
    27  // equal to t2.
    28  func CompareTimes(t1, t2 time.Time) int {
    29  	switch {
    30  	case t1.Before(t2):
    31  		return -1
    32  	case t1.After(t2):
    33  		return 1
    34  	default:
    35  		return 0
    36  	}
    37  }
    38  
    39  // CompareNumbers returns -1, 1 or 0 depending on whether n1 is less than,
    40  // greater than or equal to n2. n1 and n2 must be signed integer, unsigned
    41  // integer, or floating-point values, but they need not be the same type.
    42  //
    43  // If both types are integers or both floating-point, CompareNumbers behaves
    44  // like Go comparisons on those types. If one operand is integer and the other
    45  // is floating-point, CompareNumbers correctly compares the mathematical values
    46  // of the numbers, without loss of precision.
    47  func CompareNumbers(n1, n2 interface{}) (int, error) {
    48  	v1, ok := n1.(reflect.Value)
    49  	if !ok {
    50  		v1 = reflect.ValueOf(n1)
    51  	}
    52  	v2, ok := n2.(reflect.Value)
    53  	if !ok {
    54  		v2 = reflect.ValueOf(n2)
    55  	}
    56  	f1, err := toBigFloat(v1)
    57  	if err != nil {
    58  		return 0, err
    59  	}
    60  	f2, err := toBigFloat(v2)
    61  	if err != nil {
    62  		return 0, err
    63  	}
    64  	return f1.Cmp(f2), nil
    65  }
    66  
    67  func toBigFloat(x reflect.Value) (*big.Float, error) {
    68  	var f big.Float
    69  	switch x.Kind() {
    70  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    71  		f.SetInt64(x.Int())
    72  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    73  		f.SetUint64(x.Uint())
    74  	case reflect.Float32, reflect.Float64:
    75  		f.SetFloat64(x.Float())
    76  	default:
    77  		typ := "nil"
    78  		if x.IsValid() {
    79  			typ = fmt.Sprint(x.Type())
    80  		}
    81  		return nil, fmt.Errorf("%v of type %s is not a number", x, typ)
    82  	}
    83  	return &f, nil
    84  }