Compute with dated monetary values.
Project description
Dated Money
Dated Money is a Python library for manipulating monetary values with control over the date on which currency conversions take place. It represents each monetary value as an amount (stored as a Decimal in cents) and a currency, along with a corresponding date.
It differs from the money package in that it treats the date as a first-class element.
It downloads and saves today's conversion rates from https://www.exchangerate-api.com/ using your API key (see below). You may need a paid account for the fetching of rates for days other than today to work.
Features
- Perform arithmetic operations on monetary values with different currencies and dates
- Convert monetary values between currencies based on exchange rates for specific dates
- Fetch and cache exchange rates from external APIs or local repositories
- Flexible configuration through environment variables
Installation
You can install Dated Money using pip:
pip install dated-money
Usage
Basic Examples
from decimal import Decimal as Dec
from dmon import Money, Currency
# Create a Money class with EUR as the base currency and conversion rates from a specific date
date_a = '2022-07-14'
Eur = Money(Currency.EUR, date_a)
# Create a Money class with AUD as the base currency and conversion rates from the same date
Aud = Money(base_currency='A$', base_date=date_a)
# Create monetary values in different currencies
price_eur = Eur(100) # €100
price_usd = Eur(120, Currency.USD) # $120
price_gbp = Eur(80, '£') # £80
# Values are stored in cents and can be accessed in any currency
assert Eur(23, '€').cents('eur') == 2300
assert Eur(40).cents('usd') == Dec('4020.100502512562832012897042')
# Values can be created in any currency, regardless of the base currency
assert Eur(20, '£') == Aud(20, '£')
# Perform arithmetic operations
total = price_eur + price_usd + price_gbp
assert str(total) == '€270.40' # Total in the base currency (EUR)
# Convert to a specific currency
total_usd = total.to(Currency.USD)
assert str(total_usd) == '$303.89'
# Compare monetary values
assert price_eur < price_usd
assert price_gbp == Eur(80, Currency.GBP)
Operations with Different Currencies and Dates
You can perform operations on monetary values with different currencies and conversion dates:
date_a = '2022-07-14'
date_b = '2022-01-07'
Eur = Money(Currency.EUR, date_a)
OldEur = Money('€', date_b)
Aud = Money(Currency.AUD, date_a)
# Operations between instances with different dates return an instance with the base date of the first element
adds = OldEur(10) + Eur(30)
assert adds.amount() == 40
assert adds.on_date == OldEur.base_date
# Operations between instances with different currencies return a result in the base currency
result = Eur(10, '$') + Eur(20, 'CAD')
assert result.currency == Currency.EUR
# Changing the reference dates affects the operation results
assert Eur(10, '$', date_a) + Eur(20, 'CAD', date_a) != Eur(10, '$', date_b) + Eur(20, 'CAD', date_b)
# Perform various arithmetic operations
assert Aud(10) + Eur(20) == Aud(39.70) == Eur(39.7, 'aud')
assert Eur(20) + Aud(10) == Eur(26.73)
assert (Aud(10) + Eur(20)).currency == Currency.AUD
assert (Eur(20) + Aud(10)).currency == Currency.EUR
assert Eur(20, 'aud') + Eur(20, 'gbp') == Aud(20, 'aud') + Aud(20, 'gbp')
Using a Single Money Class
In normal use, you will probably create a single Money class with your preferred base currency and use it to handle monetary values in various currencies:
Eur = Money(Currency.EUR)
price_eur = Eur(100) # €100
price_usd = Eur(120, Currency.USD) # $120
price_gbp = Eur(80, '£') # £80
total = price_eur + price_usd + price_gbp
assert str(total) == '€304.71' # Total in the base currency (EUR)
assert price_usd.currency == Currency.USD
assert price_gbp.currency == Currency.GBP
Configuring Exchange Rates
Dated Money provides flexibility in configuring exchange rates through environment variables:
-
DMON_RATES_CACHE
: Set this to a directory where the library can maintain a cache of exchange rates (stored in an SQLite database). -
DMON_EXCHANGERATE_API_KEY
: If the rates file for a given date is not found in the repository or cache, the library will attempt to download it from https://exchangerate-api.com. Set this environment variable to your API key. Note that you may need a paid account to download historical data. -
DMON_RATES_REPO
: Set this to a directory containing a git repository with the exchange rates in amoney
subdirectory. The rates should be stored in files namedyyyy-mm-dd-rates.json
, and contain a dictionary like:
{
"conversion_rates":{
"USD":1,
"AED":3.6725,
"AFN":71.3141,
...}
}
Creating the Cache Database
To create the cache database, follow these steps:
-
Set the
DMON_RATES_CACHE
environment variable:export DMON_RATES_CACHE=~/.dmon
-
Create the database cache table:
dmon-rates --create-table
If you have a paid API key for https://exchangerate-api.com, you can set the DMON_EXCHANGERATE_API_KEY
environment variable and create your cache with:
dmon-rates --fetch-rates 2021-10-10:2021-10-20
Contributing
Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the GitHub repository.
License
Dated Money is released under the MIT License.
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
Built Distribution
File details
Details for the file dated_money-1.0.1.tar.gz
.
File metadata
- Download URL: dated_money-1.0.1.tar.gz
- Upload date:
- Size: 13.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/23.3.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | c20ebe19941a6a079365e8e8b98f3bd634bc574607cb765afc021279f8731ed7 |
|
MD5 | 97f97557803aee9cccc49a9e651bfb46 |
|
BLAKE2b-256 | 294b89201107edd60b7d8b93294b6106951dc6b18ab4e07390b406a5769c1141 |
File details
Details for the file dated_money-1.0.1-py3-none-any.whl
.
File metadata
- Download URL: dated_money-1.0.1-py3-none-any.whl
- Upload date:
- Size: 13.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/23.3.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e7601be783684d114009dd31f75023eee16993d3305a3846b4f298424d9e349d |
|
MD5 | 740d899266b75b1790249f092a208f2b |
|
BLAKE2b-256 | 0191cb919465533dfeff9ad86934a8779a88b62c6799458a21756f33213035c2 |