Skip to main content

Precise monetary calculations using integer cents with currency support and formatting

Project description

philiprehberger-money

Tests PyPI version GitHub release Last updated License Bug Reports Feature Requests Sponsor

Precise monetary calculations using integer cents with currency support and formatting.

Installation

pip install philiprehberger-money

Usage

Creating Money

from philiprehberger_money import Money

price = Money.from_major(19.99, "USD")
free = Money.zero("EUR")

Arithmetic

from philiprehberger_money import Money

a = Money.from_major(10.00, "USD")
b = Money.from_major(3.50, "USD")

total = a + b          # $13.50
diff = a - b           # $6.50
doubled = a * 2        # $20.00
split = a.divide(3)    # $3.33 (rounded)
negated = -a           # -$10.00

Safe Currency Handling

from philiprehberger_money import Money, CurrencyMismatchError

usd = Money.from_major(10, "USD")
eur = Money.from_major(10, "EUR")

usd + eur  # raises CurrencyMismatchError

Allocation (Split Without Losing Cents)

from philiprehberger_money import Money

total = Money.from_major(100.00, "USD")

# Split 50/30/20
shares = total.allocate([50, 30, 20])
# [Money($50.00), Money($30.00), Money($20.00)]

# Handles remainders correctly
odd = Money.from_major(10.00, "USD")
thirds = odd.allocate([1, 1, 1])
# [Money($3.34), Money($3.33), Money($3.33)]

Denomination Rounding

from philiprehberger_money import Money

price = Money.from_major(1.23, "USD")

# Round to nearest 5 cents
rounded = price.round_to_nearest(5)
print(rounded.format(symbol="$"))  # "$1.25"

# Round to nearest 10 cents
rounded = price.round_to_nearest(10)
print(rounded.format(symbol="$"))  # "$1.20"

Currency Conversion

from philiprehberger_money import Money

usd = Money.from_major(100, "USD")

# Direct rate
eur = usd.convert("EUR", 0.92)
print(eur.format())  # "92.00 EUR"

# Using a rates dictionary
eur = usd.convert(to="EUR", rates={"USD/EUR": 0.92})

# Using a rate provider callable
def get_rate(from_currency: str, to_currency: str) -> float:
    return 0.92  # fetch from API, database, etc.

eur = usd.convert(to="EUR", rate_provider=get_rate)

Locale-Aware Formatting

from philiprehberger_money import Money

price = Money.from_major(1234.56, "USD")

print(price.format())                 # "1234.56 USD"
print(price.format(symbol="$"))       # "$1234.56"
print(price.format(locale="en_US"))   # "$1,234.56"
print(price.format(locale="de_DE"))   # "$1.234,56"

Rounding Modes

from philiprehberger_money import Money, RoundingMode, set_default_rounding_mode

# Per-instance rounding mode
m = Money(amount_cents=5, currency="USD", rounding_mode=RoundingMode.ROUND_HALF_EVEN)
result = m.divide(2)  # 2.5 -> 2 (banker's rounding)

# Change rounding mode on existing instance
m2 = m.with_rounding_mode(RoundingMode.ROUND_UP)

# Set global default (affects all instances without explicit mode)
set_default_rounding_mode(RoundingMode.ROUND_HALF_EVEN)

Comparisons

from philiprehberger_money import Money

a = Money.from_major(10, "USD")
b = Money.from_major(20, "USD")

a < b   # True
a == b  # False
a.is_positive()  # True
a.is_zero()      # False

Zero-Decimal Currencies

from philiprehberger_money import Money

yen = Money.from_major(1000, "JPY")
print(yen.format(symbol="\u00a5"))  # "\u00a51000"

Serialization

from philiprehberger_money import Money

m = Money.from_major(19.99, "USD")

d = m.to_dict()           # {"amount_cents": 1999, "currency": "USD"}
m2 = Money.from_dict(d)   # Money(19.99 USD)

API

Function / Class Description
Money.from_major(amount, currency, *, rounding_mode=None) Create from major units (dollars, euros, etc.)
Money.zero(currency, *, rounding_mode=None) Create zero-value Money
Money.from_dict(data) Create from dict
.add(other) / + Add two Money values (same currency)
.subtract(other) / - Subtract (same currency)
.multiply(factor) / * Multiply by number
.divide(divisor) Divide by number
.allocate(ratios) Split into parts without losing cents
.round_to_nearest(step) Round minor units to nearest multiple
.convert(to, rate=None, *, rates=None, rate_provider=None) Convert to another currency using a rate, rates dict, or callable
.format(symbol=None, *, locale=None) Format as string, optionally locale-aware
.with_rounding_mode(mode) Return copy with specified rounding mode
.negate() / -m Negate amount
.abs() Absolute value
.is_zero() / .is_positive() / .is_negative() Predicates
.to_dict() Serialize to dict
.amount Major unit value as float
.decimals Currency decimal places
RoundingMode Enum: ROUND_HALF_UP, ROUND_HALF_EVEN, ROUND_DOWN, ROUND_UP
set_default_rounding_mode(mode) Set global default rounding mode
get_default_rounding_mode() Get current global default rounding mode
CurrencyMismatchError Raised on mixed-currency operations

Development

pip install -e .
python -m pytest tests/ -v

Support

If you find this package useful, consider giving it a star on GitHub — it helps motivate continued maintenance and development.

LinkedIn More packages

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

philiprehberger_money-0.4.0.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

philiprehberger_money-0.4.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file philiprehberger_money-0.4.0.tar.gz.

File metadata

  • Download URL: philiprehberger_money-0.4.0.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for philiprehberger_money-0.4.0.tar.gz
Algorithm Hash digest
SHA256 c2faf11ef4164a452f6a12fcf4536267911880c8776ab7f0dbebec7125def7ab
MD5 2bb16bf0e14ea1ec39d9406ab91dd768
BLAKE2b-256 01d246bc7753329d03cf92a4383cb3b8b1ee2a91dda11f6b236a9e2615c9ff11

See more details on using hashes here.

File details

Details for the file philiprehberger_money-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for philiprehberger_money-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f1849ae7670fb2ac866dd499e40855d095d2d1c074b6ea41b61fb7f43f3e64ac
MD5 35dfc2c179e2ec5780240bb79e75c9bd
BLAKE2b-256 660469a435d07188704a244f62d57493d320a62e0997cea255d6d5f2c8ec6ee6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page