Monetary string formatting library in Teal (and Lua).
Monetary is a pure-Teal library for string formatting numbers as currency. It is very similar (but not identical to) strfmon
as defined by GNU[1].
This library does not use the system locale. Instead we give a rough approximation by allowing the user to define the symbols used for the thousands separator, the decimal point, and currency symbol; which the default is ,
, .
, and $
respectively.
The library provides two functions, as shown by the record definition:
local type M = record
localize: function(thou: string, dec: string, cur: string)
strfmon: function(fmt: string, val: number): string
end
Say we want to format numbers for printing like:
$ 10,499.50
$ 1,234,567.00
Or without cents, rounding the values:
$ 10,500
$ 1,234,567
Localized:
€ 10.499,50
€ 1.234.567,00
€ 10.500
€ 1.234.567
We can use code as shown in doc_monetary.tl
.
local m = require "monetary"
local strfmon = m.strfmon
local localize = m.localize
local val1 = 10499.50
local val2 = 1234567
local fmt1 = "%#8.2n" -- 8 digits to left of decimal; 2 to right
local fmt2 = "%#8.0n" -- " ; 0 to right
print( strfmon(fmt1, val1) ) -- $ 10,499.50
print( strfmon(fmt1, val2) ) -- $ 1,234,567.00
print()
print( strfmon(fmt2, val1) ) -- $ 10,500
print( strfmon(fmt2, val2) ) -- $ 1,234,567
print()
print("localized...")
localize(".",",","€")
print( strfmon(fmt1, val1) ) -- € 10.499,50
print( strfmon(fmt1, val2) ) -- € 1.234.567,00
print()
print( strfmon(fmt2, val1) ) -- € 10.500
print( strfmon(fmt2, val2) ) -- € 1.234.567
localize
is used to set the separators used in the formatted string and the currency symbol. The library defaults to ,
for thousands, .
for decimal point and $
for currency. To override these defaults call localize
with the desired separators.
For example, to set .
as thousands, ,
as decimal point and €
for currency:
localize(".", ",", "€")
strfmon
is used to format a number as currency. It returns a string.
The fmt
argument has a number of optional flags between the required opening '%' and closing 'n'. They are, in order:
'^' Turn off use of thousands grouping. By default grouping is enabled.
'+','(' At most one of these is allowed. '+' is the default, which formats
negative numbers using '-'. (note: '+' is the flag, and not '-',
since '-' is used to indicate "left-justification".) To indicate
negative numbers by enclosing them in parenthesis use the '(' flag.
'!' Turn off use of currency symbol. Currency symbol is on by default.
'-' The output is left-justified. By default output is right-justified.
Justificaiton is only relevant when the entire field isn't filled.
<w> Minimum width of return string. If it is missing then default of 0
is used, which means any width is ok, and no padding is relevant, nor
is any justification relevant. If a width is given, and the output is
less than the width, the output is padded with spaces (on the left,
by default, on the right when '-' (left-justification) is enabled) in
order to make the output be <w> characters wide.
'#' Activates the context for (left-of) or (left-of and right-of) spacing
relevant to the decimal point (as opposed to spacing for the overall
field, which is driven by <w> above). By default this context is not
active.
If the context is enabled then at least the <l> field is
required. If the '.' symbol is included then the <r> field is
required.
<l> Left-of decimal point minimum width, as measured in *digits*.
Ensures that space for at least <l> number of digits is
provided. If thousands grouping is enabled, then space for
those is also included (this space is not counted as a
'digit'). For example, #6 for a value of 1000 will create a
string "$ 1,000", having ensured space for 6 digits.
'.' Seperates "left-of" from "right-of" decimal fields.
<r> Right-of decimal point minimum width, as measured in *digits*.
If <r> is 0, then no decimal point appears in the output, and
the value is rounded to be an integer. For other values of <r>
0's are padded to fill out the minimum width, or, if the
decimal portion exceeds <r> then the floating portion is
rounded to <r> places.
[1] https://www.gnu.org/software/libc/manual/html_node/Formatting-Numbers.html