finanza/currency
Currency and money types built on top of
finanza/decimal.
A Currency is a small record describing an ISO 4217
alpha-3 code together with display metadata. A
Money pairs a Decimal amount with a Currency so
arithmetic that crosses currencies is rejected with a typed error.
Both types are pub opaque. Build them through the smart
constructors new_currency and
new (for Money), or pick a catalogue value from
finanza/currency/catalog.
Types
A monetary unit identified by an ISO 4217 alpha-3 code.
pub opaque type Currency
Errors raised by currency and money operations.
pub type CurrencyError {
CurrencyMismatch(left: String, right: String)
InvalidExponent
InvalidCurrencyCode
EmptyRatios
NonPositiveRatio
ArithmeticError(error: decimal.ArithmeticError)
}
Constructors
-
CurrencyMismatch(left: String, right: String)Two operands had different currencies.
-
InvalidExponentexponentpassed tonew_currencywas out of the supported range (0–8). -
InvalidCurrencyCodecodepassed tonew_currencywas empty. -
EmptyRatiosallocatewas called with an empty ratio list. -
NonPositiveRatioallocatereceived a ratio that was zero or negative. -
ArithmeticError(error: decimal.ArithmeticError)A decimal operation overflowed the supported precision window. Inspect
errorfor the underlying decimal error.
Options passed to format. Build from
default_format and the with_* setters.
pub opaque type FormatOptions
How negative amounts are rendered in formatted output.
pub type NegativeStyle {
MinusSign
Parentheses
}
Constructors
-
MinusSign -
Parentheses
Where the currency symbol appears in formatted output.
pub type SymbolPosition {
Prefix
Suffix
NoSymbol
}
Constructors
-
Prefix -
Suffix -
NoSymbol
Values
pub fn add(
a a: Money,
b b: Money,
) -> Result(Money, CurrencyError)
Add two Money values. Both operands must share the same
currency.
pub fn allocate(
m m: Money,
ratios ratios: List(Int),
) -> Result(List(Money), CurrencyError)
Split a Money proportionally to ratios, distributing rounding
remainders to the first slots so the slices sum back to the
original amount exactly.
let bill = from_minor(units: 1000, currency: catalog.usd())
allocate(bill, [1, 1, 1])
// Ok([$3.34, $3.33, $3.33])
pub fn compare(
a a: Money,
b b: Money,
) -> Result(order.Order, CurrencyError)
Compare two money values. Both operands must share the same currency.
pub fn currency_of(m m: Money) -> Currency
The currency component of a Money. Named currency_of to avoid
a currency.currency(m) call site, which reads awkwardly given
the module name.
pub fn default_format() -> FormatOptions
Default FormatOptions: symbol prefix, ,
thousands separator, . decimal separator, leading minus sign,
no currency code suffix, and the amount is rescaled to the
currency’s minor-unit exponent (so USD always renders with two
cents, JPY with none, etc.).
pub fn divide(
m m: Money,
divisor divisor: decimal.Decimal,
mode mode: rounding.Mode,
) -> Result(Money, CurrencyError)
Divide a money value by a scalar, rounding the result to the
currency’s minor-unit exponent using mode.
pub fn equal(a a: Money, b b: Money) -> Bool
Equality test for two money values. Returns False rather than an
error on currency mismatch, mirroring ==.
pub fn exponent(c c: Currency) -> Int
Minor-unit exponent (USD = 2, JPY = 0, BHD = 3, etc.).
pub fn format(
m m: Money,
options options: FormatOptions,
) -> String
Render a money value with the given FormatOptions.
By default the amount is rescaled to the currency’s minor-unit
exponent (so 12 renders as `12.00and ¥1234 as¥1,234). Call [with_minor_units](#with_minor_units) with False` to preserve
the amount’s original precision.
pub fn from_minor(
units units: Int,
currency currency: Currency,
) -> Money
Build a Money from an integer number of minor units. The
resulting amount has exponent -currency.exponent.
from_minor(units: 1234, currency: catalog.usd()) represents
$12.34.
pub fn multiply(
m m: Money,
factor factor: decimal.Decimal,
) -> Result(Money, CurrencyError)
Multiply a money value by a scalar.
pub fn new_currency(
code code: String,
exponent exponent: Int,
symbol symbol: String,
name name: String,
) -> Result(Currency, CurrencyError)
Build a custom Currency. Use this when the desired
currency is outside the static catalogue.
code must be a non-empty string. exponent is the number of
minor-unit digits and must be in the range 0–8.
pub fn new_money(
amount amount: decimal.Decimal,
currency currency: Currency,
) -> Money
Build a Money from a Decimal and a
Currency. Named new_money rather than new to
keep symmetry with new_currency and to avoid
the surprise of currency.new returning the other type from
the module’s name.
pub fn subtract(
a a: Money,
b b: Money,
) -> Result(Money, CurrencyError)
Subtract b from a.
pub fn to_minor(
m m: Money,
mode mode: rounding.Mode,
) -> Result(Int, CurrencyError)
Convert a Money back to its minor-unit integer count, rounding
to the currency’s exponent using mode.
pub fn to_string(m m: Money) -> String
Render a money value using the default ISO-style format:
"USD 1234.56".
pub fn with_currency_code(
options options: FormatOptions,
enabled enabled: Bool,
) -> FormatOptions
Toggle whether the ISO code is appended to the rendered string.
pub fn with_decimal_separator(
options options: FormatOptions,
separator separator: String,
) -> FormatOptions
Override the decimal separator.
pub fn with_minor_units(
options options: FormatOptions,
enabled enabled: Bool,
) -> FormatOptions
Toggle whether the amount is rescaled to the currency’s
minor-unit exponent before rendering. Defaults to True; pass
False to preserve the amount’s original precision (useful when
the value carries finer-than-minor digits, e.g. for an FX rate
or a unit price).
pub fn with_negative_style(
options options: FormatOptions,
style style: NegativeStyle,
) -> FormatOptions
Override the negative-amount style.
pub fn with_symbol_position(
options options: FormatOptions,
position position: SymbolPosition,
) -> FormatOptions
Override the symbol position.
pub fn with_thousands_separator(
options options: FormatOptions,
separator separator: String,
) -> FormatOptions
Override the thousands separator.