caellion-python-commons
formatters.py
Go to the documentation of this file.
1 """!
2 This module provides various string formatters
3 """
4 
5 import math
6 
7 
8 class InvalidDurationException(Exception):
9  """!
10  This exception is raised whenever provided duration is zero or negative.
11  """
12 
13  pass
14 
15 
17  """!
18  This class provides various number formats
19  """
20 
21  def formatSI(v, dec=0):
22  """!
23  Formats number as an SI-prefixed decimal
24 
25  @param v Number to be formatted
26  @param dec Number of decimal places
27 
28  @returns formatted string
29  """
30  sign = ""
31  if v < 0:
32  sign = "-"
33  v = abs(v)
34  suffix = ""
35  SI_suffix = "kMGTPEZY"
36 
37  if v >= 1000:
38  value_mag = math.log10(v)
39 
40  suffix_index = min(len(SI_suffix) - 1, max(0, math.floor(value_mag / 3) - 1))
41 
42  value = v / pow(10, (suffix_index + 1) * 3)
43  suffix = SI_suffix[suffix_index]
44  else:
45  value = v
46 
47  return sign + ("{:." + str(dec) + "f}").format(value) + suffix
48 
49  def formatBinarySI(v, dec=0):
50  """!
51  Formats number as an SI-prefixed decimal, using binary unit prefixes (ki, Mi, etc.)
52 
53  @param v Number to be formatted
54  @param dec Number of decimal places
55 
56  @returns formatted string
57  """
58  sign = ""
59  if v < 0:
60  sign = "-"
61  v = abs(v)
62  suffix = ""
63  SI_suffix = "kMGTPEZY"
64 
65  if v >= 1024:
66  value_mag = math.log(v, 2)
67 
68  suffix_index = min(len(SI_suffix) - 1, max(0, math.floor(value_mag / 10) - 1))
69 
70  value = v / pow(2, (suffix_index + 1) * 10)
71  suffix = SI_suffix[suffix_index] + "i"
72  else:
73  value = v
74 
75  return sign + ("{:." + str(dec) + "f}").format(value) + suffix
76 
77  # for formatting less than one (0.X) with suffixes like milli
78  def formatSISubValue(v, dec=0):
79  """!
80  Formats less-than-one numbers to an SI-prefixed decimal (using prefixes like m, μ)
81 
82  @param v Number to be formatted
83  @param dec Number of decimal places
84 
85  @returns formatted string
86  """
87  sign = ""
88  if v < 0:
89  sign = "-"
90  v = abs(v)
91  SI_suffix = "mμnpfazy"
92  max_log = (len(SI_suffix)) * 3
93 
94  if v >= 1 / pow(10, max_log):
95  value_mag = -1 * math.log10(v)
96  suffix_index = math.ceil(value_mag / 3) - 1
97  value = v * pow(10, (suffix_index + 1) * 3)
98  suffix = SI_suffix[suffix_index]
99  elif v > 0:
100  value = 0
101  suffix = "y"
102  else:
103  value = 0
104  suffix = ""
105 
106  return sign + ("{:." + str(dec) + "f}").format(value) + suffix
107 
108  # for formatting less than one (0.X) with suffixes like milli, binary
109  def formatSIBinarySubValue(v, dec=0): # pragma: no mutate
110  """!
111  Formats fractional number to SI-prefixed decimal using binary unit prefixes
112 
113  @warning This is not supported
114  """
115  return "BinSubValueError"
116 
117  # router for formatting all values
118  def formatSIFullRange(v, dec):
119  """!
120  Formats number using full range (will format numbers below 1 with subvalue variant) using SI decimal unit prefixes
121 
122  @param v Number to be formatted
123  @param dec Number of decimal places
124 
125  @returns formatted string
126  """
127  if v > -1 and v < 1:
128  return NumberFormatting.formatSISubValue(v, dec)
129  else:
130  return NumberFormatting.formatSI(v, dec)
131 
132  def formatUnitsPerIntervalDynamic(units, seconds, unit):
133  """!
134  Generates an expression like "1.0kg/year"
135 
136  @param units amount of units that have happened over measurement interval
137  @param seconds measurement interval, expressed in seconds
138  @param unit name of unit (kg in example above)
139 
140  @returns formatted string, expression like "1.0kg/year"
141  """
142  if units < 0:
143  return "-" + NumberFormatting.formatUnitsPerIntervalDynamic(abs(units), seconds, unit)
144 
145  if seconds <= 0:
146  raise InvalidDurationException(str("{:s} is not a valid, positive duration").format(str(seconds)))
147 
148  units_per_second = units / seconds
149  units_per_millisecond = units_per_second / 1000.0
150  units_per_microsecond = units_per_second / 1000000.0
151  units_per_millenium = units_per_second * 1000.0 * 365.0 * 86400.0
152  units_per_century = units_per_second * 100.0 * 365.0 * 86400.0
153  units_per_year = units_per_second * 365.0 * 86400.0
154  units_per_week = units_per_second * 7.0 * 86400.0
155  units_per_day = units_per_second * 86400.0
156  units_per_hour = units_per_second * 3600.0
157  units_per_minute = units_per_second * 60.0
158 
159  if units_per_century < 1.0:
160  return str("{:.2f}{:s}/{:s}").format(units_per_millenium, unit, "millenium")
161  elif units_per_year < 1.0:
162  return str("{:.2f}{:s}/{:s}").format(units_per_century, unit, "century")
163  elif units_per_week < 1.0:
164  return str("{:.2f}{:s}/{:s}").format(units_per_year, unit, "year")
165  elif units_per_day < 1.0:
166  return str("{:.2f}{:s}/{:s}").format(units_per_week, unit, "week")
167  elif units_per_hour < 1.0:
168  return str("{:.2f}{:s}/{:s}").format(units_per_day, unit, "day")
169  elif units_per_minute < 1.0:
170  return str("{:.2f}{:s}/{:s}").format(units_per_hour, unit, "hour")
171  elif units_per_second < 1.0:
172  return str("{:.2f}{:s}/{:s}").format(units_per_minute, unit, "minute")
173  elif units_per_millisecond < 1.0:
174  return str("{:.2f}{:s}/{:s}").format(units_per_second, unit, "second")
175  elif units_per_microsecond < 1.0:
176  return str("{:.2f}{:s}/{:s}").format(units_per_millisecond, unit, "millisecond")
177  else:
178  return str("{:.2f}{:s}/{:s}").format(units_per_microsecond, unit, "microsecond")
def formatSI(v, dec=0)
Formats number as an SI-prefixed decimal.
Definition: formatters.py:21
This exception is raised whenever provided duration is zero or negative.
Definition: formatters.py:8
def formatBinarySI(v, dec=0)
Formats number as an SI-prefixed decimal, using binary unit prefixes (ki, Mi, etc.)
Definition: formatters.py:49
def formatSIFullRange(v, dec)
Formats number using full range (will format numbers below 1 with subvalue variant) using SI decimal ...
Definition: formatters.py:118
This class provides various number formats.
Definition: formatters.py:16
def formatSISubValue(v, dec=0)
Formats less-than-one numbers to an SI-prefixed decimal (using prefixes like m, μ) ...
Definition: formatters.py:78
def formatSIBinarySubValue(v, dec=0)
Formats fractional number to SI-prefixed decimal using binary unit prefixes.
Definition: formatters.py:109
def formatUnitsPerIntervalDynamic(units, seconds, unit)
Generates an expression like "1.0kg/year".
Definition: formatters.py:132