github.com/GuanceCloud/cliutils@v1.1.21/pprofparser/domain/quantity/quantity.go (about) 1 package quantity 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/GuanceCloud/cliutils/pprofparser/tools/mathtoolkit" 8 ) 9 10 type Quantity struct { 11 Value int64 12 Unit *Unit 13 } 14 15 func (q *Quantity) MarshalJSON() ([]byte, error) { 16 if q == nil { 17 return []byte("null"), nil 18 } 19 return []byte(fmt.Sprintf("\"%s\"", q.String())), nil 20 } 21 22 func (q *Quantity) SwitchToDefaultUnit() { 23 if q == nil || q.Unit == nil { 24 return 25 } 26 if q.Unit != q.Unit.Kind.DefaultUnit { 27 q.Value, _ = q.IntValueIn(q.Unit.Kind.DefaultUnit) 28 q.Unit = q.Unit.Kind.DefaultUnit 29 } 30 } 31 32 func (q *Quantity) String() string { 33 if q.Value == 0 { 34 return "No Data" 35 } 36 switch q.Unit.Kind { 37 case Count: 38 return fmt.Sprintf("%d", q.Value) 39 case Memory: 40 byt, _ := q.IntValueIn(Byte) 41 if byt >= GigaByte.Base { 42 gb, _ := q.DoubleValueIn(GigaByte) 43 return fmt.Sprintf("%.2f %s", gb, GigaByte) 44 } else if byt >= MegaByte.Base { 45 mb, _ := q.DoubleValueIn(MegaByte) 46 return fmt.Sprintf("%.2f %s", mb, MegaByte) 47 } else if byt >= KiloByte.Base { 48 kb, _ := q.DoubleValueIn(KiloByte) 49 return fmt.Sprintf("%.2f %s", kb, KiloByte) 50 } 51 return fmt.Sprintf("%d %s", byt, Byte) 52 case Duration: 53 td := q.toTimeDuration() 54 return td.String() 55 } 56 return fmt.Sprintf("%d %s", q.Value, q.Unit) 57 } 58 59 func (q *Quantity) DoubleValueIn(target *Unit) (float64, error) { 60 if q.Unit == target { 61 return float64(q.Value), nil 62 } 63 if q.Unit.Kind != target.Kind { 64 return 0, fmt.Errorf("can not convert [%s] to [%s], the kinds of the unit should be same", q.Unit, target) 65 } 66 67 return float64(q.Value) * (float64(q.Unit.Base) / float64(target.Base)), nil 68 } 69 70 func (q *Quantity) IntValueIn(target *Unit) (int64, error) { 71 if q.Unit == target { 72 return q.Value, nil 73 } 74 v, err := q.DoubleValueIn(target) 75 if err != nil { 76 return 0, err 77 } 78 return mathtoolkit.Trunc(v), nil 79 } 80 81 func (q *Quantity) Sub(sub *Quantity) *Quantity { 82 if q.Unit.Kind != sub.Unit.Kind { 83 panic("arithmetic operation between not matched unit kind") 84 } 85 86 m, n := q.Value, sub.Value 87 88 toUnit := q.Unit 89 if q.Unit.Base > sub.Unit.Base { 90 m, _ = q.IntValueIn(sub.Unit) 91 toUnit = sub.Unit 92 } else if q.Unit.Base < sub.Unit.Base { 93 n, _ = sub.IntValueIn(q.Unit) 94 } 95 96 return toUnit.Quantity(m - n) 97 } 98 99 func (q *Quantity) toTimeDuration() time.Duration { 100 if q.Unit.Kind != Duration { 101 panic("not kind of duration, can not convert") 102 } 103 104 num := time.Duration(q.Value) 105 106 switch q.Unit { 107 case NanoSecond: 108 return time.Nanosecond * num 109 case MicroSecond: 110 return time.Microsecond * num 111 case MilliSecond: 112 return time.Millisecond * num 113 case Second: 114 return time.Second * num 115 case Minute: 116 return time.Minute * num 117 case Hour: 118 return time.Hour * num 119 } 120 panic(fmt.Sprintf("not resolved duration unit: [%s]", q.Unit)) 121 }