Initial revision
[python_utils.git] / conversion_utils.py
1 #!/usr/bin/env python3
2
3 from numbers import Number
4 from typing import Callable
5
6
7 class Converter(object):
8     def __init__(self,
9                  name: str,
10                  category: str,
11                  to_canonical: Callable,
12                  from_canonical: Callable,
13                  unit: str) -> None:
14         self.name = name
15         self.category = category
16         self.to_canonical = to_canonical
17         self.from_canonical = from_canonical
18         self.unit = unit
19
20     def to_canonical(self, n: Number) -> Number:
21         return self.to_canonical(n)
22
23     def from_canonical(self, n: Number) -> Number:
24         return self.from_canonical(n)
25
26     def unit_suffix(self) -> str:
27         return self.unit
28
29
30 conversion_catalog = {
31     "Fahrenheit": Converter("Fahrenheit",
32                             "temperature",
33                             lambda f: (f - 32.0) * 0.55555555,
34                             lambda c: c * 1.8 + 32.0,
35                             "°F"),
36     "Celsius": Converter("Celsius",
37                          "temperature",
38                          lambda c: c,
39                          lambda c: c,
40                          "°C"),
41     "Kelvin": Converter("Kelvin",
42                         "temperature",
43                         lambda k: k - 273.15,
44                         lambda c: c + 273.15,
45                         "°K"),
46 }
47
48
49 def convert(magnitude: Number,
50             from_thing: str,
51             to_thing: str) -> Number:
52     src = conversion_catalog.get(from_thing, None)
53     dst = conversion_catalog.get(to_thing, None)
54     if src is None or dst is None:
55         raise ValueError("No known conversion")
56     return _convert(magnitude, src, dst)
57
58
59 def _convert(magnitude: Number,
60              from_unit: Converter,
61              to_unit: Converter) -> Number:
62     canonical = from_unit.to_canonical(magnitude)
63     converted = to_unit.from_canonical(canonical)
64     return converted
65
66
67 def f_to_c(temp_f: float) -> float:
68     """Fahrenheit to Celsius."""
69     return convert(temp_f, "Fahrenheit", "Celsius")
70
71
72 def c_to_f(temp_c: float) -> float:
73     """Celsius to Fahrenheit."""
74     return convert(temp_c, "Celsius", "Fahrenheit")