LanguageValues and typesStandard typesMoney and banking
Money
On this page
An amount of money: a whole number of a currency's smallest units, and the currency.
Use it for every amount of money. Never hold money in a Decimal: this type can't lose a penny to rounding, and it can't add pounds to euros. For an amount with whether tax is included, use Price. To fix the currency, build your own type on it.
Shape
One value, with no fields to fill in. As text it reads GBP 1234.50.
Example
money.from_minor(1050, Currency.gbp)text.parse(raw, as: Money) reads one from text that comes from outside. Text that isn't one at all fails malformed, such as 10.50, GBP 10.505 or GBP 10.5.
These operations give one: money.allocate, money.convert, money.from_minor, money.of, money.split and money.sum.
Good to know
money.from_minor(1050, Currency.gbp)is £10.50, since it takes pence.money.oftakes a decimal amount instead.- A percentage scales it:
price * 120%adds 20%. To share it out, usemoney.split, which loses nothing: £10.00 three ways is £3.34, £3.33 and £3.33.price / 3is refused. <compares two amounts in one currency. With two different currencies the compiler refuses it, or, if a currency is only known while running, it fails withcurrency_mismatch.- A narrower type is often better:
type Sterling = Money { currency: Currency.gbp min: 0 }. ==tells you whether two are the same, and<andlist.sort_bycompare and sort them.
In JSON
An object of its parts, in a request, a response or json.write:
{"amount":-500,"currency":"GBP"}{"amount":5,"currency":"GBP"}{"amount":1050,"currency":"GBP"}
Details
Text form, storage, how it is shown, and operations
Money is in the group Money and banking, and has been in Jadpo since 0.1.0.
Text form
text.from writes one standard text form, the same form text.parse reads back: GBP -5.00, GBP 0.05 and GBP 10.50.
How it is stored
It is stored in 2 columns, each named for the field, _ and its suffix. This is GBP 10.50:
| Column | Type | Holds |
|---|---|---|
<field>_amount |
bigint |
1050 |
<field>_currency |
char(3) |
'GBP' |
How it is shown to people
text.format(value, locale:) shows it to people in their locale. A call may also give precision:, display: or sign:.
With locale: Locale.en_gb:
| Value | Shown |
|---|---|
GBP -5.00 |
-£5.00 |
GBP 0.05 |
£0.05 |
GBP 10.50 |
£10.50 |
GBP 1234.50 |
£1,234.50 |
Operations
money.allocate(total: Money, ratios: List<Int>) -> List<Money>:totalshared in proportion toratios, whole numbers never below 0, at least one of them; a share of ratio 0 is nothing.money.convert(value: Money, rate: ExchangeRate) -> Money:valueinrate'stocurrency, from itsfromone: the major units timesrate.rate, rounded half to even to a minor unit, so £10.50 at aGBP/EURrate of 1.17 is €12.28. It fails withcurrency_mismatchwhenvalueisn't inrate.from, unless that is known: an inverted rate is then a compile error. The rate is one the app holds; nothing here fetches one.money.currency(value: Money) -> Currency: The currencyvalueis in.money.from_minor(amount: Int, currency: Currency) -> Money:amountminor units ofcurrency:money.from_minor(1050, Currency.gbp)is £10.50.money.minor(value: Money) -> Int:value's minor units: 1050 for £10.50.money.of(amount: Decimal, currency: Currency) -> Money:amountmajor units ofcurrency, aDecimal:money.of(10.50, Currency.gbp)is £10.50. It fails withtoo_many_placesfor more places than the currency has (10.505 in pounds), unless the currency is written out and the amount proved to have no more.money.split(total: Money, parts: Int) -> List<Money>:totalinpartsnear-equal shares,partsat least 1: £10.00 in 3 is £3.34, £3.33 and £3.33.money.sum(items: List<Money>, currency: Currency) -> Money: The items added up incurrency, the zero an empty list gives. It fails withcurrency_mismatchfor an item in another currency, unless the items' type fixescurrency.
It also takes text.parse, text.from, text.format, json.read, json.write and ==. How every standard type behaves says how they work.
Markdown for agents: /docs/types/type-money.md.Built from Jadpo main at aee2e8f.