github.com/scaleway/scaleway-cli@v1.11.1/pkg/pricing/usage.go (about) 1 package pricing 2 3 import ( 4 "math/big" 5 "time" 6 ) 7 8 // Usage represents a billing usage 9 type Usage struct { 10 Object *Object 11 Quantity *big.Rat 12 } 13 14 // NewUsageByPath returns a new Usage with defaults fetched from a path 15 func NewUsageByPath(objectPath string) Usage { 16 return NewUsageByPathWithQuantity(objectPath, ratZero) 17 } 18 19 // NewUsageByPathWithQuantity returns a NewUsageByPath with a specific quantity 20 func NewUsageByPathWithQuantity(objectPath string, quantity *big.Rat) Usage { 21 return NewUsageWithQuantity(CurrentPricing.GetByPath(objectPath), quantity) 22 } 23 24 // NewUsageWithQuantity returns a new Usage with quantity 25 func NewUsageWithQuantity(object *Object, quantity *big.Rat) Usage { 26 return Usage{ 27 Object: object, 28 Quantity: quantity, 29 } 30 } 31 32 // NewUsage returns a new Usage 33 func NewUsage(object *Object) Usage { 34 return NewUsageWithQuantity(object, ratZero) 35 } 36 37 // SetQuantity sets the quantity of an Usage 38 func (u *Usage) SetQuantity(quantity *big.Rat) error { 39 u.Quantity = ratMax(quantity, ratZero) 40 return nil 41 } 42 43 // SetDuration sets the duration of an Usage 44 func (u *Usage) SetDuration(duration time.Duration) error { 45 minutes := new(big.Rat).SetFloat64(duration.Minutes()) 46 factor := new(big.Rat).SetInt64((u.Object.UsageGranularity / time.Minute).Nanoseconds()) 47 quantity := new(big.Rat).Quo(minutes, factor) 48 ceil := new(big.Rat).SetInt(ratCeil(quantity)) 49 return u.SetQuantity(ceil) 50 } 51 52 // SetStartEnd sets the start date and the end date of an Usage 53 func (u *Usage) SetStartEnd(start, end time.Time) error { 54 roundedStart := start.Round(u.Object.UsageGranularity) 55 if roundedStart.After(start) { 56 roundedStart = roundedStart.Add(-u.Object.UsageGranularity) 57 } 58 roundedEnd := end.Round(u.Object.UsageGranularity) 59 if roundedEnd.Before(end) { 60 roundedEnd = roundedEnd.Add(u.Object.UsageGranularity) 61 } 62 return u.SetDuration(roundedEnd.Sub(roundedStart)) 63 } 64 65 // BillableQuantity returns the billable quantity of an Usage 66 func (u *Usage) BillableQuantity() *big.Rat { 67 if u.Quantity.Cmp(ratZero) < 1 { 68 return big.NewRat(0, 1) 69 } 70 71 //return math.Ceil(u.Quantity/u.Object.UnitQuantity) * u.Object.UnitQuantity 72 quantityQuotient := new(big.Rat).Quo(u.Quantity, u.Object.UnitQuantity) 73 ceil := new(big.Rat).SetInt(ratCeil(quantityQuotient)) 74 return new(big.Rat).Mul(ceil, u.Object.UnitQuantity) 75 } 76 77 // LostQuantity returns the lost quantity of an Usage 78 func (u *Usage) LostQuantity() *big.Rat { 79 //return u.BillableQuantity() - math.Max(u.Quantity, 0) 80 81 return new(big.Rat).Sub(u.BillableQuantity(), ratMax(u.Quantity, ratZero)) 82 } 83 84 // Total returns the total of an Usage 85 func (u *Usage) Total() *big.Rat { 86 //return math.Min(u.Object.UnitPrice * u.BillableQuantity(), u.Object.UnitPriceCap) 87 88 total := new(big.Rat).Mul(u.BillableQuantity(), u.Object.UnitPrice) 89 total = total.Quo(total, u.Object.UnitQuantity) 90 return ratMin(total, u.Object.UnitPriceCap) 91 } 92 93 // TotalString returns a string representing the total price of an Usage + its currency 94 func (u *Usage) TotalString() string { 95 return PriceString(u.Total(), u.Object.Currency) 96 }