philiprehberger-money
Precise monetary calculations using integer cents with currency support and formatting.
Installation
pip install philiprehberger-money
Usage
from philiprehberger_money import Money
price = Money.from_major(19.99, "USD")
print(price.format(symbol="$")) # "$19.99"
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)
Sum Multiple Values
from philiprehberger_money import Money
items = [Money.from_major(10, "USD"), Money.from_major(20, "USD"), Money.from_major(30, "USD")]
total = Money.sum(items)
print(total.format(symbol="$")) # "$60.00"
Percentage
from philiprehberger_money import Money
price = Money.from_major(200, "USD")
tip = price.percentage(15)
print(tip.format(symbol="$")) # "$30.00"
Even Split
from philiprehberger_money import Money
bill = Money.from_major(100, "USD")
shares = bill.split_even(3)
# [Money($33.34), Money($33.33), Money($33.33)]
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 |
Money.sum(moneys) |
Sum a list of Money values (same currency) |
.percentage(pct) |
Calculate a percentage of this money value |
.split_even(n) |
Split evenly into n parts, distributing remainders |
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 project useful:
License
Release files for philiprehberger-money 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| philiprehberger_money-0.5.0.tar.gz | 12.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| philiprehberger_money-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.4 kB
Release files / philiprehberger_money-0.5.0.tar.gz
| Download URL | philiprehberger_money-0.5.0.tar.gz |
|---|---|
| Size | 12.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d446e81e509d587f696515274a8523d1238e433ea61965611b27643fba01fd82
|
|
BLAKE2b-256 checksum How to use checksums |
ffa8197decee35d2c8122569ad17575e8f37f3cccfddabdd9d321820d79354bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / philiprehberger_money-0.5.0-py3-none-any.whl
| Download URL | philiprehberger_money-0.5.0-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
721c6d807212fe056423cf349c0a11436683531c3d7eb1ccf52b0fdf6f4662de
|
|
BLAKE2b-256 checksum How to use checksums |
82d8d90b8890c0debe7dc26fe979fd4be9957eee4dcba3cadc6bd74c15b0c4c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|