Skip to main content

Compute with dated monetary values.

Project description

dated-money — dmon.money.Money

Manipulate monetary values, each consisting in an amount (stored as a Decimal in cents) and a currency, with control on the date on which currency conversions take place.

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). If your account is free currency exchanges will only work for today, or for dates for which a conversion rate json file is found. If your account is paid all dates will work.

Examples

from decimal import Decimal as Dec
from dmon import Money, Currency

# Compute in eur with today's conversion rates (default)
Eur = Money(Currency.EUR)

# Compute in gbp with today's conversion rates
Gbp = Money('£')

assert Eur(40).cents() == Dec('4000')
assert Eur(40).to('$').cents() == Dec('4020.100502512562832012897042')
assert Eur(20) < Gbp(20)
assert Eur(20, '£') == Eur(20, 'gbp') == Eur(20, Currency.GBP) == Gbp(20)

# We can define the default date for conversions when creating the class
OldUsd = Money('$', on='2022-01-07')
assert str(OldUsd(20, 'eur').to('$')) == '$22.61'
assert str(Eur(20, 'eur').to('$')) == '$20.13'  # With today's rates

# Computations are done in the default currency of the class Eur
assert str(Eur(20, 'aud') + Eur(20, 'gbp')) == '€37.00'

# If we move to another date the values differ
Eur.to_date('2022-01-07')
assert str(Eur(20, 'aud') + Eur(20, 'gbp')) == '€36.65'

# If we use two classes with different dates the output will have the later date:
assert str(Eur(20, 'aud') + Gbp(20, 'gbp')) == '€36.23'
assert str(Gbp(20) + Eur(20, 'aud')) == '£30.61'

assert Eur(20) / Gbp(20) == Dec('0.8500402576489532855181620688')
assert Eur(20) / 2 == Eur(10)
assert str(1.2 * Eur(20)) == '€24.00'
assert str(1.2 * Eur(20).to(Currency.CAD)) == 'C$31.53'

paid = Gbp(10)
amount_cents, currency = paid.as_tuple()
assert (amount_cents, currency) == (Dec('1000'), 'gbp')
assert Gbp((amount_cents, currency), amount_is_cents=True) == paid

Installation

pip install dated-money

Usage

The class factory Money returns a class that knows its currency and the date for which currency transformations should be done. When the on argument is None (default) the date is set to today's. If it is a date string, like '2021-10-29', it will do the conversions with the date's exchange rate (assuming that it can find the json file with the rates, otherwise it will fail).

Important All computations are done with cents stored as Decimal, but comparisons are are rounded to the second decimal. So, for example,

paid = Gbp(10)
paid_usd = paid.to('$')
paid_usd.cents()  # Decimal('1183.992422448496305219877141')
str(paid_usd)     # '$11.84'

# If we initialize with a string instead of a float it will be an exact Decimal.
native_usd = Gbp('11.84', 'usd')
native_usd.cents()  # Decimal('1184.00')
assert native_usd == paid_usd
assert native_usd.cents() != paid_usd.cents()
native_usd.cents() - paid_usd.cents()  # Decimal('0.007577551503694780122859')

Create the cache database

Set up the DMON_RATES_CACHE environment variable:

export DMON_RATES_CACHE=~/.dmon

and then create the database cache table:

dmon-rates --create-table

If you have a paid API key for https://exchangerate-api.com you can set up the DMON_EXCHANGERATE_API_KEY environment variable, and create your cache with

dmon-rates --fetch-rates 2021-10-10:2021-10-20

Environment variables

The DMON_RATES_REPO environment variable can point to a directory containing a git repo with the rates in a money subdirectory. The rates should be in files called yyyy-mm-dd-rates.json, which contain a dictionary like:

    {
     "conversion_rates":{
      "USD":1,
      "AED":3.6725,
      "AFN":71.3141,
    ...}
    }

The DMON_RATES_CACHE environment variable can point to a directory where a cache is maintained (sqlite database).

If the rates file for a given date is not found in any of the above, the library will attempt to download it from https://exchangerate-api.com. You will need an API key in the DMON_EXCHANGERATE_API_KEY environment variable. You may need a paid accont to download historical data (ie, not the current day).

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

dated_money-0.1.0.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

dated_money-0.1.0-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file dated_money-0.1.0.tar.gz.

File metadata

  • Download URL: dated_money-0.1.0.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.2 Darwin/23.3.0

File hashes

Hashes for dated_money-0.1.0.tar.gz
Algorithm Hash digest
SHA256 141995346b00da49fb835764756e408a839c1dc8a57b8d751200fed83120c44a
MD5 c5a13725f2c67283396df32e8bb32d10
BLAKE2b-256 e5e2ceb3b17c3b472dc2095d44b38a747bdb46b5484bb216f94da5d164dd626d

See more details on using hashes here.

File details

Details for the file dated_money-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dated_money-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.1 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

Hashes for dated_money-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dfd45541a73da0575496613eb2757e361a036aae47ab25d425d31990e7a0307a
MD5 4d37216aaa1c44f13144e298b4fc1df3
BLAKE2b-256 a25b1240500d8420caa8c01e94460a3f39bef76093e0f141455b46683ab32abf

See more details on using hashes here.

Supported by

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