Skip to main content

philiprehberger-money

Tests PyPI version Last updated

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:

⭐ Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

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)

Source distribution for philiprehberger-money 0.5.0
File Size Uploaded
philiprehberger_money-0.5.0.tar.gz 12.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for philiprehberger-money 0.5.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page