forked from s3lph/matemat
59 lines
2.2 KiB
Python
59 lines
2.2 KiB
Python
|
|
|
|
def format_chf(value: int, with_currencysign: bool = True, plus_sign: bool = False) -> str:
|
|
"""
|
|
Formats a centime value into a commonly understood representation ("CHF -13.37").
|
|
|
|
:param value: The value to format, in centimes.
|
|
:param with_currencysign: Whether to include the currency prefix ("CHF ") in the output.
|
|
:param plus_sign: Whether to denote positive values with an explicit "+" sign before the value.
|
|
:return: A human-readable string representation.
|
|
"""
|
|
sign: str = ''
|
|
if value < 0:
|
|
# As // and % round towards -Inf, convert into a positive value and prepend the negative sign
|
|
sign = '-'
|
|
value = -value
|
|
elif plus_sign:
|
|
sign = '+'
|
|
# Split into full francs and fractions (centimes)
|
|
full: int = value // 100
|
|
frac: int = value % 100
|
|
csign: str = 'CHF ' if with_currencysign else ''
|
|
# Put it all together; centimes are always padded with 2 zeros
|
|
return f'{csign}{sign}{full}.{frac:02}'
|
|
|
|
|
|
def parse_chf(value: str) -> int:
|
|
"""
|
|
Parse a currency value into machine-readable format (integer centimes). The prefix "CHF", the decimal point, and
|
|
digits after the decimal point are optional.
|
|
|
|
:param value: The value to parse.
|
|
:return: An integer representation of the value.
|
|
:raises: Value error: If more than two digits after the decimal point are present.
|
|
"""
|
|
# Remove optional leading "CHF" and strip whitespace
|
|
value = value.strip()
|
|
if value.startswith('CHF'):
|
|
value = value[3:]
|
|
value = value.strip()
|
|
if '.' not in value:
|
|
# already is an integer; parse and turn into centimes
|
|
return int(value, 10) * 100
|
|
# Split at the decimal point
|
|
full, frac = value.split('.', 1)
|
|
if len(frac) > 2:
|
|
raise ValueError('Needs max. 2 digits after decimal point')
|
|
elif len(frac) < 2:
|
|
# Right-pad fraction with zeros ("x." -> "x.00", "x.x" -> "x.x0")
|
|
frac = frac + '0' * (2 - len(frac))
|
|
# Parse both parts
|
|
ifrac: int = int(frac, 10)
|
|
ifull: int = int(full, 10)
|
|
if ifrac < 0:
|
|
raise ValueError('Fraction part must not be negative.')
|
|
if full.startswith('-'):
|
|
ifrac = -ifrac
|
|
# Combine into centime integer
|
|
return ifull * 100 + ifrac
|