Skip to main content

Precise monetary calculations using integer cents with currency support and formatting

Project description

philiprehberger-money

Tests PyPI version Last updated

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 project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

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.1.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.1-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: philiprehberger_money-0.4.1.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.1.tar.gz
Algorithm Hash digest
SHA256 74549304947982e88fec8d93bc9b8a6e16bde0595ee2a2f4d69b11dde0b8fd53
MD5 e062b834a0d82167b3091ff7435878a5
BLAKE2b-256 c592ed1803047d7668fabde104404bc80e945e99f2491bc2e02e9d02d0010718

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for philiprehberger_money-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8483db95f9bd80d56fd13d0c66dc54f4f145ee34a4c8e140c122c00707da9287
MD5 cdc93642f6b00c690c02e17c35d94b0e
BLAKE2b-256 cbe21051641048990f01c898abd00b33b3c904819913992cb36535f1de6dbf16

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