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  }