from .money_amount import Money from .money_format_data import CURRENCIES def format_money(amount: Money) -> str: """Render a monetary amount as text. Not every currency has two decimal places: yen has none, Kuwaiti dinar has three. Dividing by 100 to display an amount is wrong about as often as it is right, so the precision comes from the currency table. """ fmt = next((c for c in CURRENCIES if c.code == amount.currency), None) if fmt is None: raise ValueError('no formatting rules for currency "%s"' % (amount.currency,)) negative = amount.minor < 0 digits = str(abs(amount.minor)).rjust(fmt.digits + 1, "0") whole = digits[: len(digits) - fmt.digits] fraction = digits[len(digits) - fmt.digits :] grouped = "" for i, ch in enumerate(whole): if i > 0 and (len(whole) - i) % 3 == 0: grouped += fmt.group_separator grouped += ch number = grouped + fmt.decimal_separator + fraction if fmt.digits > 0 else grouped body = fmt.symbol + number if fmt.symbol_before else number + fmt.symbol return "-" + body if negative else body