3 from numbers import Number
4 from typing import Callable
9 class Converter(object):
13 to_canonical: Callable,
14 from_canonical: Callable,
17 self.category = category
18 self.to_canonical_f = to_canonical
19 self.from_canonical_f = from_canonical
22 def to_canonical(self, n: Number) -> Number:
23 return self.to_canonical_f(n)
25 def from_canonical(self, n: Number) -> Number:
26 return self.from_canonical_f(n)
28 def unit_suffix(self) -> str:
32 conversion_catalog = {
33 "Second": Converter("Second",
38 "Minute": Converter("Minute",
40 lambda m: (m * constants.SECONDS_PER_MINUTE),
41 lambda s: (s / constants.SECONDS_PER_MINUTE),
43 "Hour": Converter("Hour",
45 lambda h: (h * constants.SECONDS_PER_HOUR),
46 lambda s: (s / constants.SECONDS_PER_HOUR),
48 "Day": Converter("Day",
50 lambda d: (d * constants.SECONDS_PER_DAY),
51 lambda s: (s / constants.SECONDS_PER_DAY),
53 "Week": Converter("Week",
55 lambda w: (w * constants.SECONDS_PER_WEEK),
56 lambda s: (s / constants.SECONDS_PER_WEEK),
58 "Fahrenheit": Converter("Fahrenheit",
60 lambda f: (f - 32.0) * 0.55555555,
61 lambda c: c * 1.8 + 32.0,
63 "Celsius": Converter("Celsius",
68 "Kelvin": Converter("Kelvin",
76 def convert(magnitude: Number,
78 to_thing: str) -> float:
79 src = conversion_catalog.get(from_thing, None)
80 dst = conversion_catalog.get(to_thing, None)
81 if src is None or dst is None:
82 raise ValueError("No known conversion")
83 if src.category != dst.category:
84 raise ValueError("Incompatible conversion")
85 return _convert(magnitude, src, dst)
88 def _convert(magnitude: Number,
90 to_unit: Converter) -> float:
91 canonical = from_unit.to_canonical(magnitude)
92 converted = to_unit.from_canonical(canonical)
93 return float(converted)
96 def sec_to_min(s: float) -> float:
97 return convert(s, "Second", "Minute")
100 def sec_to_hour(s: float) -> float:
101 return convert(s, "Second", "Hour")
104 def sec_to_day(s: float) -> float:
105 return convert(s, "Second", "Day")
108 def sec_to_week(s: float) -> float:
109 return convert(s, "Second", "Week")
112 def min_to_sec(m: float) -> float:
113 return convert(m, "Minute", "Second")
116 def min_to_hour(m: float) -> float:
117 return convert(m, "Minute", "Hour")
120 def min_to_day(m: float) -> float:
121 return convert(m, "Minute", "Day")
124 def min_to_week(m: float) -> float:
125 return convert(m, "Minute", "Week")
128 def hour_to_sec(h: float) -> float:
129 return convert(h, "Hour", "Second")
132 def hour_to_min(h: float) -> float:
133 return convert(h, "Hour", "Minute")
136 def hour_to_day(h: float) -> float:
137 return convert(h, "Hour", "Day")
140 def hour_to_week(h: float) -> float:
141 return convert(h, "Hour", "Week")
144 def day_to_sec(d: float) -> float:
145 return convert(d, "Day", "Second")
148 def day_to_min(d: float) -> float:
149 return convert(d, "Day", "Minute")
152 def day_to_hour(d: float) -> float:
153 return convert(d, "Day", "Hour")
156 def day_to_week(d: float) -> float:
157 return convert(d, "Day", "Week")
160 def week_to_sec(w: float) -> float:
161 return convert(w, "Week", "Second")
164 def week_to_min(w: float) -> float:
165 return convert(w, "Week", "Minute")
168 def week_to_hour(w: float) -> float:
169 return convert(w, "Week", "Hour")
172 def week_to_day(w: float) -> float:
173 return convert(w, "Week", "Day")
176 def f_to_c(temp_f: float) -> float:
177 """Fahrenheit to Celsius."""
178 return convert(temp_f, "Fahrenheit", "Celsius")
181 def c_to_f(temp_c: float) -> float:
182 """Celsius to Fahrenheit."""
183 return convert(temp_c, "Celsius", "Fahrenheit")