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