Money, Rate, CentCount and a bunch of bugfixes.
[python_utils.git] / type / rate.py
1 #!/usr/bin/env python3
2
3 from typing import Optional
4
5
6 class Rate(object):
7     def __init__(
8             self,
9             multiplier: Optional[float] = None,
10             *,
11             percentage: Optional[float] = None,
12             percent_change: Optional[float] = None,
13     ):
14         count = 0
15         if multiplier is not None:
16             if isinstance(multiplier, str):
17                 multiplier = multiplier.replace('%', '')
18                 m = float(multiplier)
19                 m /= 100
20                 self.multiplier = m
21             else:
22                 self.multiplier = multiplier
23             count += 1
24         if percentage is not None:
25             self.multiplier = percentage / 100
26             count += 1
27         if percent_change is not None:
28             self.multiplier = 1.0 + percent_change / 100
29             count += 1
30         if count != 1:
31             raise Exception(
32                 'Exactly one of percentage, percent_change or multiplier is required.'
33             )
34
35     def apply_to(self, other):
36         return self.__mul__(other)
37
38     def of(self, other):
39         return self.__mul__(other)
40
41     def __float__(self):
42         return self.multiplier
43
44     def __mul__(self, other):
45         return self.multiplier * float(other)
46
47     __rmul__ = __mul__
48
49     def __truediv__(self, other):
50         return self.multiplier / float(other)
51
52     def __add__(self, other):
53         return self.multiplier + float(other)
54
55     __radd__ = __add__
56
57     def __sub__(self, other):
58         return self.multiplier - float(other)
59
60     def __eq__(self, other):
61         return self.multiplier == float(other)
62
63     def __ne__(self, other):
64         return not self.__eq__(other)
65
66     def __lt__(self, other):
67         return self.multiplier < float(other)
68
69     def __gt__(self, other):
70         return self.multiplier > float(other)
71
72     def __le__(self, other):
73         return self < other or self == other
74
75     def __ge__(self, other):
76         return self > other or self == other
77
78     def __hash__(self):
79         return self.multiplier
80
81     def __repr__(self,
82                  *,
83                  relative=False,
84                  places=3):
85         if relative:
86             percentage = (self.multiplier - 1.0) * 100.0
87         else:
88             percentage = self.multiplier * 100.0
89         return f'{percentage:+.{places}f}%'