From 31f245efd592cec6a18424f3b81f17570676bd8c Mon Sep 17 00:00:00 2001 From: daniel witz Date: Sun, 5 May 2019 11:51:08 +0300 Subject: [PATCH 01/10] fill currencies map and add format as subunits --- README.md | 5 +++ currency.go | 80 +++++++++++++++++++++++++++++++++------------ formatter.go | 6 ++++ formatter_test.go | 82 +++++++++++++++++++++++++++++++++++++++++++++++ money.go | 6 ++++ money_test.go | 20 ++++++++++++ 6 files changed, 178 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 146ec30..c5242d8 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,11 @@ To format and return Money as a string use `Display()`. ```go money.New(123456789, "EUR").Display() // €1,234,567.89 ``` +To format and return Money as a float64 representing the amount value in the currency's subunit use `AsSubunits()`. + +```go +money.New(123456789, "EUR").AsSubunits() // 1234567.89 +``` Contributing - diff --git a/currency.go b/currency.go index 95c1be5..54c105a 100644 --- a/currency.go +++ b/currency.go @@ -4,7 +4,7 @@ import ( "strings" ) -// Currency represents money currency information required for formatting. +// Currency represents money currency information required for formatting type Currency struct { Code string Fraction int @@ -14,55 +14,71 @@ type Currency struct { Thousand string } -// currencies represents a collection of currency. +// currencies represents a collection of currency var currencies = map[string]*Currency{ "AED": {Decimal: ".", Thousand: ",", Code: "AED", Fraction: 2, Grapheme: ".\u062f.\u0625", Template: "1 $"}, "AFN": {Decimal: ".", Thousand: ",", Code: "AFN", Fraction: 2, Grapheme: "\u060b", Template: "1 $"}, "ALL": {Decimal: ".", Thousand: ",", Code: "ALL", Fraction: 2, Grapheme: "L", Template: "$1"}, "AMD": {Decimal: ".", Thousand: ",", Code: "AMD", Fraction: 2, Grapheme: "\u0564\u0580.", Template: "1 $"}, - "ANG": {Decimal: ".", Thousand: ",", Code: "ANG", Fraction: 2, Grapheme: "\u0192", Template: "$1"}, + "ANG": {Decimal: ",", Thousand: ".", Code: "ANG", Fraction: 2, Grapheme: "\u0192", Template: "$1"}, + "AOA": {Decimal: ".", Thousand: ",", Code: "AOA", Fraction: 2, Grapheme: "Kz", Template: "1$"}, "ARS": {Decimal: ".", Thousand: ",", Code: "ARS", Fraction: 2, Grapheme: "$", Template: "$1"}, "AUD": {Decimal: ".", Thousand: ",", Code: "AUD", Fraction: 2, Grapheme: "$", Template: "$1"}, - "AWG": {Decimal: ".", Thousand: ",", Code: "AWG", Fraction: 2, Grapheme: "\u0192", Template: "$1"}, + "AWG": {Decimal: ".", Thousand: ",", Code: "AWG", Fraction: 2, Grapheme: "\u0192", Template: "1$"}, "AZN": {Decimal: ".", Thousand: ",", Code: "AZN", Fraction: 2, Grapheme: "\u20bc", Template: "$1"}, "BAM": {Decimal: ".", Thousand: ",", Code: "BAM", Fraction: 2, Grapheme: "KM", Template: "$1"}, "BBD": {Decimal: ".", Thousand: ",", Code: "BBD", Fraction: 2, Grapheme: "$", Template: "$1"}, + "BDT": {Decimal: ".", Thousand: ",", Code: "BDT", Fraction: 2, Grapheme: "\u09f3", Template: "$1"}, "BGN": {Decimal: ".", Thousand: ",", Code: "BGN", Fraction: 2, Grapheme: "\u043b\u0432", Template: "$1"}, "BHD": {Decimal: ".", Thousand: ",", Code: "BHD", Fraction: 3, Grapheme: ".\u062f.\u0628", Template: "1 $"}, + "BIF": {Decimal: ".", Thousand: ",", Code: "BIF", Fraction: 0, Grapheme: "Fr", Template: "1$"}, "BMD": {Decimal: ".", Thousand: ",", Code: "BMD", Fraction: 2, Grapheme: "$", Template: "$1"}, "BND": {Decimal: ".", Thousand: ",", Code: "BND", Fraction: 2, Grapheme: "$", Template: "$1"}, "BOB": {Decimal: ".", Thousand: ",", Code: "BOB", Fraction: 2, Grapheme: "Bs.", Template: "$1"}, "BRL": {Decimal: ".", Thousand: ",", Code: "BRL", Fraction: 2, Grapheme: "R$", Template: "$1"}, "BSD": {Decimal: ".", Thousand: ",", Code: "BSD", Fraction: 2, Grapheme: "$", Template: "$1"}, + "BTN": {Decimal: ".", Thousand: ",", Code: "BTN", Fraction: 2, Grapheme: "Nu.", Template: "1$"}, "BWP": {Decimal: ".", Thousand: ",", Code: "BWP", Fraction: 2, Grapheme: "P", Template: "$1"}, - "BYN": {Decimal: ".", Thousand: ",", Code: "BYN", Fraction: 2, Grapheme: "p.", Template: "1 $"}, - "BYR": {Decimal: ".", Thousand: ",", Code: "BYR", Fraction: 0, Grapheme: "p.", Template: "1 $"}, + "BYN": {Decimal: ",", Thousand: " ", Code: "BYN", Fraction: 2, Grapheme: "p.", Template: "1 $"}, + "BYR": {Decimal: ",", Thousand: " ", Code: "BYR", Fraction: 0, Grapheme: "p.", Template: "1 $"}, "BZD": {Decimal: ".", Thousand: ",", Code: "BZD", Fraction: 2, Grapheme: "BZ$", Template: "$1"}, "CAD": {Decimal: ".", Thousand: ",", Code: "CAD", Fraction: 2, Grapheme: "$", Template: "$1"}, + "CDF": {Decimal: ".", Thousand: ",", Code: "CDF", Fraction: 2, Grapheme: "FC", Template: "1$"}, "CHF": {Decimal: ".", Thousand: ",", Code: "CHF", Fraction: 2, Grapheme: "CHF", Template: "1 $"}, - "CLP": {Decimal: ".", Thousand: ",", Code: "CLP", Fraction: 0, Grapheme: "$", Template: "$1"}, + "CLF": {Decimal: ",", Thousand: ".", Code: "CLF", Fraction: 4, Grapheme: "UF", Template: "$1"}, + "CLP": {Decimal: ",", Thousand: ".", Code: "CLP", Fraction: 0, Grapheme: "$", Template: "$1"}, "CNY": {Decimal: ".", Thousand: ",", Code: "CNY", Fraction: 2, Grapheme: "\u5143", Template: "1 $"}, - "COP": {Decimal: ".", Thousand: ",", Code: "COP", Fraction: 0, Grapheme: "$", Template: "$1"}, + "COP": {Decimal: ",", Thousand: ".", Code: "COP", Fraction: 2, Grapheme: "$", Template: "$1"}, "CRC": {Decimal: ".", Thousand: ",", Code: "CRC", Fraction: 2, Grapheme: "\u20a1", Template: "$1"}, + "CUC": {Decimal: ".", Thousand: ",", Code: "CUC", Fraction: 2, Grapheme: "$", Template: "1$"}, "CUP": {Decimal: ".", Thousand: ",", Code: "CUP", Fraction: 2, Grapheme: "$MN", Template: "$1"}, + "CVE": {Decimal: ".", Thousand: ",", Code: "CVE", Fraction: 2, Grapheme: "$", Template: "1$"}, "CZK": {Decimal: ".", Thousand: ",", Code: "CZK", Fraction: 2, Grapheme: "K\u010d", Template: "1 $"}, + "DJF": {Decimal: ".", Thousand: ",", Code: "DJF", Fraction: 0, Grapheme: "Fdj", Template: "1 $"}, "DKK": {Decimal: ".", Thousand: ",", Code: "DKK", Fraction: 2, Grapheme: "kr", Template: "1 $"}, "DOP": {Decimal: ".", Thousand: ",", Code: "DOP", Fraction: 2, Grapheme: "RD$", Template: "$1"}, "DZD": {Decimal: ".", Thousand: ",", Code: "DZD", Fraction: 2, Grapheme: ".\u062f.\u062c", Template: "1 $"}, "EEK": {Decimal: ".", Thousand: ",", Code: "EEK", Fraction: 2, Grapheme: "kr", Template: "$1"}, "EGP": {Decimal: ".", Thousand: ",", Code: "EGP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, + "ERN": {Decimal: ".", Thousand: ",", Code: "ERN", Fraction: 2, Grapheme: "Nfk", Template: "1 $"}, + "ETB": {Decimal: ".", Thousand: ",", Code: "ETB", Fraction: 2, Grapheme: "Br", Template: "1 $"}, "EUR": {Decimal: ".", Thousand: ",", Code: "EUR", Fraction: 2, Grapheme: "\u20ac", Template: "$1"}, "FJD": {Decimal: ".", Thousand: ",", Code: "FJD", Fraction: 2, Grapheme: "$", Template: "$1"}, "FKP": {Decimal: ".", Thousand: ",", Code: "FKP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, "GBP": {Decimal: ".", Thousand: ",", Code: "GBP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, + "GEL": {Decimal: ".", Thousand: ",", Code: "GEL", Fraction: 2, Grapheme: "\u10da", Template: "1 $"}, "GGP": {Decimal: ".", Thousand: ",", Code: "GGP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, "GHC": {Decimal: ".", Thousand: ",", Code: "GHC", Fraction: 2, Grapheme: "\u00a2", Template: "$1"}, + "GHS": {Decimal: ".", Thousand: ",", Code: "GHS", Fraction: 2, Grapheme: "\u20b5", Template: "$1"}, "GIP": {Decimal: ".", Thousand: ",", Code: "GIP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, + "GMD": {Decimal: ".", Thousand: ",", Code: "GMD", Fraction: 2, Grapheme: "D", Template: "1 $"}, + "GNF": {Decimal: ".", Thousand: ",", Code: "GNF", Fraction: 0, Grapheme: "FG", Template: "1 $"}, "GTQ": {Decimal: ".", Thousand: ",", Code: "GTQ", Fraction: 2, Grapheme: "Q", Template: "$1"}, "GYD": {Decimal: ".", Thousand: ",", Code: "GYD", Fraction: 2, Grapheme: "$", Template: "$1"}, "HKD": {Decimal: ".", Thousand: ",", Code: "HKD", Fraction: 2, Grapheme: "$", Template: "$1"}, "HNL": {Decimal: ".", Thousand: ",", Code: "HNL", Fraction: 2, Grapheme: "L", Template: "$1"}, - "HRK": {Decimal: ".", Thousand: ",", Code: "HRK", Fraction: 2, Grapheme: "kn", Template: "$1"}, + "HRK": {Decimal: ",", Thousand: ".", Code: "HRK", Fraction: 2, Grapheme: "kn", Template: "1 $"}, + "HTG": {Decimal: ",", Thousand: ".", Code: "HTG", Fraction: 2, Grapheme: "G", Template: "1 $"}, "HUF": {Decimal: ".", Thousand: ",", Code: "HUF", Fraction: 0, Grapheme: "Ft", Template: "$1"}, "IDR": {Decimal: ".", Thousand: ",", Code: "IDR", Fraction: 2, Grapheme: "Rp", Template: "$1"}, "ILS": {Decimal: ".", Thousand: ",", Code: "ILS", Fraction: 2, Grapheme: "\u20aa", Template: "$1"}, @@ -70,7 +86,7 @@ var currencies = map[string]*Currency{ "INR": {Decimal: ".", Thousand: ",", Code: "INR", Fraction: 2, Grapheme: "\u20b9", Template: "$1"}, "IQD": {Decimal: ".", Thousand: ",", Code: "IQD", Fraction: 3, Grapheme: ".\u062f.\u0639", Template: "1 $"}, "IRR": {Decimal: ".", Thousand: ",", Code: "IRR", Fraction: 2, Grapheme: "\ufdfc", Template: "1 $"}, - "ISK": {Decimal: ".", Thousand: ",", Code: "ISK", Fraction: 2, Grapheme: "kr", Template: "$1"}, + "ISK": {Decimal: ",", Thousand: ".", Code: "ISK", Fraction: 0, Grapheme: "kr", Template: "$1"}, "JEP": {Decimal: ".", Thousand: ",", Code: "JEP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, "JMD": {Decimal: ".", Thousand: ",", Code: "JMD", Fraction: 2, Grapheme: "J$", Template: "$1"}, "JOD": {Decimal: ".", Thousand: ",", Code: "JOD", Fraction: 3, Grapheme: ".\u062f.\u0625", Template: "1 $"}, @@ -78,6 +94,7 @@ var currencies = map[string]*Currency{ "KES": {Decimal: ".", Thousand: ",", Code: "KES", Fraction: 2, Grapheme: "KSh", Template: "$1"}, "KGS": {Decimal: ".", Thousand: ",", Code: "KGS", Fraction: 2, Grapheme: "\u0441\u043e\u043c", Template: "$1"}, "KHR": {Decimal: ".", Thousand: ",", Code: "KHR", Fraction: 2, Grapheme: "\u17db", Template: "$1"}, + "KMF": {Decimal: ".", Thousand: ",", Code: "KMF", Fraction: 0, Grapheme: "CF", Template: "$1"}, "KPW": {Decimal: ".", Thousand: ",", Code: "KPW", Fraction: 0, Grapheme: "\u20a9", Template: "$1"}, "KRW": {Decimal: ".", Thousand: ",", Code: "KRW", Fraction: 0, Grapheme: "\u20a9", Template: "$1"}, "KWD": {Decimal: ".", Thousand: ",", Code: "KWD", Fraction: 3, Grapheme: ".\u062f.\u0643", Template: "1 $"}, @@ -87,16 +104,20 @@ var currencies = map[string]*Currency{ "LBP": {Decimal: ".", Thousand: ",", Code: "LBP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, "LKR": {Decimal: ".", Thousand: ",", Code: "LKR", Fraction: 2, Grapheme: "\u20a8", Template: "$1"}, "LRD": {Decimal: ".", Thousand: ",", Code: "LRD", Fraction: 2, Grapheme: "$", Template: "$1"}, + "LSL": {Decimal: ".", Thousand: ",", Code: "LSL", Fraction: 2, Grapheme: "L", Template: "$1"}, "LTL": {Decimal: ".", Thousand: ",", Code: "LTL", Fraction: 2, Grapheme: "Lt", Template: "$1"}, "LVL": {Decimal: ".", Thousand: ",", Code: "LVL", Fraction: 2, Grapheme: "Ls", Template: "1 $"}, "LYD": {Decimal: ".", Thousand: ",", Code: "LYD", Fraction: 3, Grapheme: ".\u062f.\u0644", Template: "1 $"}, "MAD": {Decimal: ".", Thousand: ",", Code: "MAD", Fraction: 2, Grapheme: ".\u062f.\u0645", Template: "1 $"}, + "MDL": {Decimal: ".", Thousand: ",", Code: "MDL", Fraction: 2, Grapheme: "lei", Template: "1 $"}, "MKD": {Decimal: ".", Thousand: ",", Code: "MKD", Fraction: 2, Grapheme: "\u0434\u0435\u043d", Template: "$1"}, "MMK": {Decimal: ".", Thousand: ",", Code: "MMK", Fraction: 2, Grapheme: "K", Template: "$1"}, "MNT": {Decimal: ".", Thousand: ",", Code: "MNT", Fraction: 2, Grapheme: "\u20ae", Template: "$1"}, + "MOP": {Decimal: ".", Thousand: ",", Code: "MOP", Fraction: 2, Grapheme: "P", Template: "1 $"}, "MUR": {Decimal: ".", Thousand: ",", Code: "MUR", Fraction: 2, Grapheme: "\u20a8", Template: "$1"}, - "MXN": {Decimal: ".", Thousand: ",", Code: "MXN", Fraction: 2, Grapheme: "$", Template: "$1"}, + "MVR": {Decimal: ".", Thousand: ",", Code: "MVR", Fraction: 2, Grapheme: "MVR", Template: "1 $"}, "MWK": {Decimal: ".", Thousand: ",", Code: "MWK", Fraction: 2, Grapheme: "MK", Template: "$1"}, + "MXN": {Decimal: ".", Thousand: ",", Code: "MXN", Fraction: 2, Grapheme: "$", Template: "$1"}, "MYR": {Decimal: ".", Thousand: ",", Code: "MYR", Fraction: 2, Grapheme: "RM", Template: "$1"}, "MZN": {Decimal: ".", Thousand: ",", Code: "MZN", Fraction: 2, Grapheme: "MT", Template: "$1"}, "NAD": {Decimal: ".", Thousand: ",", Code: "NAD", Fraction: 2, Grapheme: "$", Template: "$1"}, @@ -108,6 +129,7 @@ var currencies = map[string]*Currency{ "OMR": {Decimal: ".", Thousand: ",", Code: "OMR", Fraction: 3, Grapheme: "\ufdfc", Template: "1 $"}, "PAB": {Decimal: ".", Thousand: ",", Code: "PAB", Fraction: 2, Grapheme: "B/.", Template: "$1"}, "PEN": {Decimal: ".", Thousand: ",", Code: "PEN", Fraction: 2, Grapheme: "S/", Template: "$1"}, + "PGK": {Decimal: ".", Thousand: ",", Code: "PGK", Fraction: 2, Grapheme: "K", Template: "1 $"}, "PHP": {Decimal: ".", Thousand: ",", Code: "PHP", Fraction: 2, Grapheme: "\u20b1", Template: "$1"}, "PKR": {Decimal: ".", Thousand: ",", Code: "PKR", Fraction: 2, Grapheme: "\u20a8", Template: "$1"}, "PLN": {Decimal: ".", Thousand: ",", Code: "PLN", Fraction: 2, Grapheme: "z\u0142", Template: "1 $"}, @@ -117,38 +139,54 @@ var currencies = map[string]*Currency{ "RSD": {Decimal: ".", Thousand: ",", Code: "RSD", Fraction: 2, Grapheme: "\u0414\u0438\u043d.", Template: "$1"}, "RUB": {Decimal: ".", Thousand: ",", Code: "RUB", Fraction: 2, Grapheme: "\u20bd", Template: "1 $"}, "RUR": {Decimal: ".", Thousand: ",", Code: "RUR", Fraction: 2, Grapheme: "\u20bd", Template: "1 $"}, + "RWF": {Decimal: ".", Thousand: ",", Code: "RWF", Fraction: 0, Grapheme: "FRw", Template: "1 $"}, "SAR": {Decimal: ".", Thousand: ",", Code: "SAR", Fraction: 2, Grapheme: "\ufdfc", Template: "1 $"}, "SBD": {Decimal: ".", Thousand: ",", Code: "SBD", Fraction: 2, Grapheme: "$", Template: "$1"}, "SCR": {Decimal: ".", Thousand: ",", Code: "SCR", Fraction: 2, Grapheme: "\u20a8", Template: "$1"}, + "SDG": {Decimal: ".", Thousand: ",", Code: "SDG", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, "SEK": {Decimal: ".", Thousand: ",", Code: "SEK", Fraction: 2, Grapheme: "kr", Template: "1 $"}, "SGD": {Decimal: ".", Thousand: ",", Code: "SGD", Fraction: 2, Grapheme: "$", Template: "$1"}, "SHP": {Decimal: ".", Thousand: ",", Code: "SHP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, - "SOS": {Decimal: ".", Thousand: ",", Code: "SOS", Fraction: 2, Grapheme: "S", Template: "$1"}, + "SKK": {Decimal: ".", Thousand: ",", Code: "SKK", Fraction: 2, Grapheme: "Sk", Template: "$1"}, + "SLL": {Decimal: ".", Thousand: ",", Code: "SLL", Fraction: 2, Grapheme: "Le", Template: "1 $"}, + "SOS": {Decimal: ".", Thousand: ",", Code: "SOS", Fraction: 2, Grapheme: "Sh", Template: "1 $"}, "SRD": {Decimal: ".", Thousand: ",", Code: "SRD", Fraction: 2, Grapheme: "$", Template: "$1"}, - "SVC": {Decimal: ".", Thousand: ",", Code: "SVC", Fraction: 2, Grapheme: "$", Template: "$1"}, - "SYP": {Decimal: ".", Thousand: ",", Code: "SYP", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, + "SSP": {Decimal: ".", Thousand: ",", Code: "SSP", Fraction: 2, Grapheme: "\u00a3", Template: "1 $"}, + "STD": {Decimal: ".", Thousand: ",", Code: "STD", Fraction: 2, Grapheme: "Db", Template: "1 $"}, + "SVC": {Decimal: ".", Thousand: ",", Code: "SVC", Fraction: 2, Grapheme: "\u20a1", Template: "$1"}, + "SYP": {Decimal: ".", Thousand: ",", Code: "SYP", Fraction: 2, Grapheme: "\u00a3", Template: "1 $"}, + "SZL": {Decimal: ".", Thousand: ",", Code: "SZL", Fraction: 2, Grapheme: "\u00a3", Template: "$1"}, "THB": {Decimal: ".", Thousand: ",", Code: "THB", Fraction: 2, Grapheme: "\u0e3f", Template: "$1"}, + "TJS": {Decimal: ".", Thousand: ",", Code: "TJS", Fraction: 2, Grapheme: "SM", Template: "1 $"}, + "TMT": {Decimal: ".", Thousand: ",", Code: "TMT", Fraction: 2, Grapheme: "T", Template: "1 $"}, "TND": {Decimal: ".", Thousand: ",", Code: "TND", Fraction: 3, Grapheme: ".\u062f.\u062a", Template: "1 $"}, + "TOP": {Decimal: ".", Thousand: ",", Code: "TOP", Fraction: 2, Grapheme: "T$", Template: "$1"}, "TRL": {Decimal: ".", Thousand: ",", Code: "TRL", Fraction: 2, Grapheme: "\u20a4", Template: "$1"}, "TRY": {Decimal: ".", Thousand: ",", Code: "TRY", Fraction: 2, Grapheme: "\u20ba", Template: "$1"}, "TTD": {Decimal: ".", Thousand: ",", Code: "TTD", Fraction: 2, Grapheme: "TT$", Template: "$1"}, "TWD": {Decimal: ".", Thousand: ",", Code: "TWD", Fraction: 0, Grapheme: "NT$", Template: "$1"}, "TZS": {Decimal: ".", Thousand: ",", Code: "TZS", Fraction: 0, Grapheme: "TSh", Template: "$1"}, - "UAH": {Decimal: ".", Thousand: ",", Code: "UAH", Fraction: 2, Grapheme: "\u20b4", Template: "$1"}, - "UGX": {Decimal: ".", Thousand: ",", Code: "UGX", Fraction: 0, Grapheme: "USh", Template: "$1"}, + "UAH": {Decimal: ".", Thousand: ",", Code: "UAH", Fraction: 2, Grapheme: "\u20b4", Template: "1 $"}, + "UGX": {Decimal: ".", Thousand: ",", Code: "UGX", Fraction: 0, Grapheme: "USh", Template: "1 $"}, "USD": {Decimal: ".", Thousand: ",", Code: "USD", Fraction: 2, Grapheme: "$", Template: "$1"}, - "UYU": {Decimal: ".", Thousand: ",", Code: "UYU", Fraction: 0, Grapheme: "$U", Template: "$1"}, + "UYU": {Decimal: ".", Thousand: ",", Code: "UYU", Fraction: 2, Grapheme: "$U", Template: "$1"}, "UZS": {Decimal: ".", Thousand: ",", Code: "UZS", Fraction: 2, Grapheme: "so\u2019m", Template: "$1"}, "VEF": {Decimal: ".", Thousand: ",", Code: "VEF", Fraction: 2, Grapheme: "Bs", Template: "$1"}, "VND": {Decimal: ".", Thousand: ",", Code: "VND", Fraction: 0, Grapheme: "\u20ab", Template: "1 $"}, + "VUV": {Decimal: ".", Thousand: ",", Code: "VUV", Fraction: 0, Grapheme: "Vt", Template: "$1"}, + "WST": {Decimal: ".", Thousand: ",", Code: "WST", Fraction: 2, Grapheme: "T", Template: "1 $"}, + "XAF": {Decimal: ".", Thousand: ",", Code: "XAF", Fraction: 0, Grapheme: "Fr", Template: "1 $"}, + "XAG": {Decimal: ".", Thousand: ",", Code: "XAG", Fraction: 0, Grapheme: "oz t", Template: "1 $"}, + "XAU": {Decimal: ".", Thousand: ",", Code: "XAU", Fraction: 0, Grapheme: "oz t", Template: "1 $"}, "XCD": {Decimal: ".", Thousand: ",", Code: "XCD", Fraction: 2, Grapheme: "$", Template: "$1"}, + "XDR": {Decimal: ".", Thousand: ",", Code: "XDR", Fraction: 0, Grapheme: "SDR", Template: "1 $"}, "YER": {Decimal: ".", Thousand: ",", Code: "YER", Fraction: 2, Grapheme: "\ufdfc", Template: "1 $"}, "ZAR": {Decimal: ".", Thousand: ",", Code: "ZAR", Fraction: 2, Grapheme: "R", Template: "$1"}, "ZMW": {Decimal: ".", Thousand: ",", Code: "ZMW", Fraction: 2, Grapheme: "ZK", Template: "$1"}, "ZWD": {Decimal: ".", Thousand: ",", Code: "ZWD", Fraction: 2, Grapheme: "Z$", Template: "$1"}, } -// AddCurrency lets you insert or update currency in currencies list. +// AddCurrency lets you insert or update currency in currencies list func AddCurrency(Code, Grapheme, Template, Decimal, Thousand string, Fraction int) *Currency { currencies[Code] = &Currency{ Code: Code, @@ -172,7 +210,7 @@ func GetCurrency(code string) *Currency { } // Formatter returns currency formatter representing -// used currency structure. +// used currency structure func (c *Currency) Formatter() *Formatter { return &Formatter{ Fraction: c.Fraction, @@ -184,12 +222,12 @@ func (c *Currency) Formatter() *Formatter { } // getDefault represent default currency if currency is not found in currencies list. -// Grapheme and Code fields will be changed by currency code. +// Grapheme and Code fields will be changed by currency code func (c *Currency) getDefault() *Currency { return &Currency{Decimal: ".", Thousand: ",", Code: c.Code, Fraction: 2, Grapheme: c.Code, Template: "1$"} } -// get extended currency using currencies list. +// get extended currency using currencies list func (c *Currency) get() *Currency { if curr, ok := currencies[c.Code]; ok { return curr diff --git a/formatter.go b/formatter.go index 89adef9..1d06be9 100644 --- a/formatter.go +++ b/formatter.go @@ -1,6 +1,7 @@ package money import ( + "math" "strconv" "strings" ) @@ -54,6 +55,11 @@ func (f *Formatter) Format(amount int64) string { return sa } +// ToSubunits returns float64 representing the value in sub units using the currency data +func (f *Formatter) ToSubunits(amount int64) float64 { + return float64(amount) / float64(math.Pow10(f.Fraction)) +} + // abs return absolute value of given integer. func (f Formatter) abs(amount int64) int64 { if amount < 0 { diff --git a/formatter_test.go b/formatter_test.go index bae2a78..00544ee 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -85,3 +85,85 @@ func TestFormatter_Format(t *testing.T) { } } } + +func TestFormatter_ToSubunits(t *testing.T) { + tcs := []struct { + fraction int + decimal string + thousand string + grapheme string + template string + amount int64 + expected float64 + }{ + {2, ".", ",", "$", "1 $", 0, 0.00}, + {2, ".", ",", "$", "1 $", 1, 0.01}, + {2, ".", ",", "$", "1 $", 12, 0.12}, + {2, ".", ",", "$", "1 $", 123, 1.23}, + {2, ".", ",", "$", "1 $", 1234, 12.34}, + {2, ".", ",", "$", "1 $", 12345, 123.45}, + {2, ".", ",", "$", "1 $", 123456, 1234.56}, + {2, ".", ",", "$", "1 $", 1234567, 12345.67}, + {2, ".", ",", "$", "1 $", 12345678, 123456.78}, + {2, ".", ",", "$", "1 $", 123456789, 1234567.89}, + + {2, ".", ",", "$", "1 $", -1, -0.01}, + {2, ".", ",", "$", "1 $", -12, -0.12}, + {2, ".", ",", "$", "1 $", -123, -1.23}, + {2, ".", ",", "$", "1 $", -1234, -12.34}, + {2, ".", ",", "$", "1 $", -12345, -123.45}, + {2, ".", ",", "$", "1 $", -123456, -1234.56}, + {2, ".", ",", "$", "1 $", -1234567, -12345.67}, + {2, ".", ",", "$", "1 $", -12345678, -123456.78}, + {2, ".", ",", "$", "1 $", -123456789, -1234567.89}, + + {3, ".", "", "$", "1 $", 1, 0.001}, + {3, ".", "", "$", "1 $", 12, 0.012}, + {3, ".", "", "$", "1 $", 123, 0.123}, + {3, ".", "", "$", "1 $", 1234, 1.234}, + {3, ".", "", "$", "1 $", 12345, 12.345}, + {3, ".", "", "$", "1 $", 123456, 123.456}, + {3, ".", "", "$", "1 $", 1234567, 1234.567}, + {3, ".", "", "$", "1 $", 12345678, 12345.678}, + {3, ".", "", "$", "1 $", 123456789, 123456.789}, + + {2, ".", ",", "£", "$1", 1, 0.01}, + {2, ".", ",", "£", "$1", 12, 0.12}, + {2, ".", ",", "£", "$1", 123, 1.23}, + {2, ".", ",", "£", "$1", 1234, 12.34}, + {2, ".", ",", "£", "$1", 12345, 123.45}, + {2, ".", ",", "£", "$1", 123456, 1234.56}, + {2, ".", ",", "£", "$1", 1234567, 12345.67}, + {2, ".", ",", "£", "$1", 12345678, 123456.78}, + {2, ".", ",", "£", "$1", 123456789, 1234567.89}, + + {0, ".", ",", "NT$", "$1", 1, 1}, + {0, ".", ",", "NT$", "$1", 12, 12}, + {0, ".", ",", "NT$", "$1", 123, 123}, + {0, ".", ",", "NT$", "$1", 1234, 1234}, + {0, ".", ",", "NT$", "$1", 12345, 12345}, + {0, ".", ",", "NT$", "$1", 123456, 123456}, + {0, ".", ",", "NT$", "$1", 1234567, 1234567}, + {0, ".", ",", "NT$", "$1", 12345678, 12345678}, + {0, ".", ",", "NT$", "$1", 123456789, 123456789}, + + {0, ".", ",", "NT$", "$1", -1, -1}, + {0, ".", ",", "NT$", "$1", -12, -12}, + {0, ".", ",", "NT$", "$1", -123, -123}, + {0, ".", ",", "NT$", "$1", -1234, -1234}, + {0, ".", ",", "NT$", "$1", -12345, -12345}, + {0, ".", ",", "NT$", "$1", -123456, -123456}, + {0, ".", ",", "NT$", "$1", -1234567, -1234567}, + {0, ".", ",", "NT$", "$1", -12345678, -12345678}, + {0, ".", ",", "NT$", "$1", -123456789, -123456789}, + } + + for _, tc := range tcs { + formatter := NewFormatter(tc.fraction, tc.decimal, tc.thousand, tc.grapheme, tc.template) + r := formatter.ToSubunits(tc.amount) + + if r != tc.expected { + t.Errorf("Expected %d formatted to sub units to be %f got %f", tc.amount, tc.expected, r) + } + } +} diff --git a/money.go b/money.go index 5bf9140..660c28b 100644 --- a/money.go +++ b/money.go @@ -233,3 +233,9 @@ func (m *Money) Display() string { c := m.currency.get() return c.Formatter().Format(m.amount.val) } + +// AsSubUnits lets represent Money struct as subunits (float64) in given Currency value +func (m *Money) AsSubunits() float64 { + c := m.currency.get() + return c.Formatter().ToSubunits(m.amount.val) +} diff --git a/money_test.go b/money_test.go index 681a455..9dd5ba8 100644 --- a/money_test.go +++ b/money_test.go @@ -565,6 +565,26 @@ func TestMoney_Display(t *testing.T) { } } +func TestMoney_AsSubunits(t *testing.T) { + tcs := []struct { + amount int64 + code string + expected float64 + }{ + {100, "AED", 1.00}, + {1, "USD", 0.01}, + } + + for _, tc := range tcs { + m := New(tc.amount, tc.code) + r := m.AsSubunits() + + if r != tc.expected { + t.Errorf("Expected value as subunits of %d to be %f got %f", tc.amount, tc.expected, r) + } + } +} + func TestMoney_Allocate3(t *testing.T) { pound := New(100, "GBP") parties, err := pound.Allocate(33, 33, 33) From b00401c042631a5cb6eaa83aa6cf3bd7e1c678bb Mon Sep 17 00:00:00 2001 From: daniel witz Date: Sun, 5 May 2019 11:52:30 +0300 Subject: [PATCH 02/10] change go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2bc65b0..3b11dab 100644 --- a/go.mod +++ b/go.mod @@ -1 +1 @@ -module github.com/Rhymond/go-money +module github.com/danielwitz/go-money From f70ca8081b7f609532373f7d4cfb6fa447efcd9f Mon Sep 17 00:00:00 2001 From: daniel witz Date: Sun, 5 May 2019 12:21:49 +0300 Subject: [PATCH 03/10] change name to major units instead of subunits --- formatter.go | 4 ++-- formatter_test.go | 6 +++--- money.go | 6 +++--- money_test.go | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/formatter.go b/formatter.go index 1d06be9..228b2a7 100644 --- a/formatter.go +++ b/formatter.go @@ -55,8 +55,8 @@ func (f *Formatter) Format(amount int64) string { return sa } -// ToSubunits returns float64 representing the value in sub units using the currency data -func (f *Formatter) ToSubunits(amount int64) float64 { +// ToMajorUnits returns float64 representing the value in sub units using the currency data +func (f *Formatter) ToMajorUnits(amount int64) float64 { return float64(amount) / float64(math.Pow10(f.Fraction)) } diff --git a/formatter_test.go b/formatter_test.go index 00544ee..8158bd4 100644 --- a/formatter_test.go +++ b/formatter_test.go @@ -86,7 +86,7 @@ func TestFormatter_Format(t *testing.T) { } } -func TestFormatter_ToSubunits(t *testing.T) { +func TestFormatter_ToMajorUnits(t *testing.T) { tcs := []struct { fraction int decimal string @@ -160,10 +160,10 @@ func TestFormatter_ToSubunits(t *testing.T) { for _, tc := range tcs { formatter := NewFormatter(tc.fraction, tc.decimal, tc.thousand, tc.grapheme, tc.template) - r := formatter.ToSubunits(tc.amount) + r := formatter.ToMajorUnits(tc.amount) if r != tc.expected { - t.Errorf("Expected %d formatted to sub units to be %f got %f", tc.amount, tc.expected, r) + t.Errorf("Expected %d formatted to major units to be %f got %f", tc.amount, tc.expected, r) } } } diff --git a/money.go b/money.go index 660c28b..724882b 100644 --- a/money.go +++ b/money.go @@ -234,8 +234,8 @@ func (m *Money) Display() string { return c.Formatter().Format(m.amount.val) } -// AsSubUnits lets represent Money struct as subunits (float64) in given Currency value -func (m *Money) AsSubunits() float64 { +// AsMajorUnits lets represent Money struct as subunits (float64) in given Currency value +func (m *Money) AsMajorUnits() float64 { c := m.currency.get() - return c.Formatter().ToSubunits(m.amount.val) + return c.Formatter().ToMajorUnits(m.amount.val) } diff --git a/money_test.go b/money_test.go index 9dd5ba8..0aa5ab3 100644 --- a/money_test.go +++ b/money_test.go @@ -565,7 +565,7 @@ func TestMoney_Display(t *testing.T) { } } -func TestMoney_AsSubunits(t *testing.T) { +func TestMoney_AsMajorUnits(t *testing.T) { tcs := []struct { amount int64 code string @@ -577,10 +577,10 @@ func TestMoney_AsSubunits(t *testing.T) { for _, tc := range tcs { m := New(tc.amount, tc.code) - r := m.AsSubunits() + r := m.AsMajorUnits() if r != tc.expected { - t.Errorf("Expected value as subunits of %d to be %f got %f", tc.amount, tc.expected, r) + t.Errorf("Expected value as major units of %d to be %f got %f", tc.amount, tc.expected, r) } } } From e2a38fb44988c403da35f1f035ecca7723ee3ba1 Mon Sep 17 00:00:00 2001 From: daniel witz Date: Sun, 5 May 2019 12:23:27 +0300 Subject: [PATCH 04/10] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c5242d8..e39826d 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ money.New(123456789, "EUR").Display() // €1,234,567.89 To format and return Money as a float64 representing the amount value in the currency's subunit use `AsSubunits()`. ```go -money.New(123456789, "EUR").AsSubunits() // 1234567.89 +money.New(123456789, "EUR").AsMajorUnits() // 1234567.89 ``` Contributing From e3fbdbffa90eb33bdac32bc45b56099ead8a45aa Mon Sep 17 00:00:00 2001 From: daniel witz Date: Sun, 12 May 2019 11:18:27 +0300 Subject: [PATCH 05/10] add all the . back --- currency.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/currency.go b/currency.go index 54c105a..762d153 100644 --- a/currency.go +++ b/currency.go @@ -4,7 +4,7 @@ import ( "strings" ) -// Currency represents money currency information required for formatting +// Currency represents money currency information required for formatting. type Currency struct { Code string Fraction int @@ -14,7 +14,7 @@ type Currency struct { Thousand string } -// currencies represents a collection of currency +// currencies represents a collection of currency. var currencies = map[string]*Currency{ "AED": {Decimal: ".", Thousand: ",", Code: "AED", Fraction: 2, Grapheme: ".\u062f.\u0625", Template: "1 $"}, "AFN": {Decimal: ".", Thousand: ",", Code: "AFN", Fraction: 2, Grapheme: "\u060b", Template: "1 $"}, @@ -186,7 +186,7 @@ var currencies = map[string]*Currency{ "ZWD": {Decimal: ".", Thousand: ",", Code: "ZWD", Fraction: 2, Grapheme: "Z$", Template: "$1"}, } -// AddCurrency lets you insert or update currency in currencies list +// AddCurrency lets you insert or update currency in currencies list. func AddCurrency(Code, Grapheme, Template, Decimal, Thousand string, Fraction int) *Currency { currencies[Code] = &Currency{ Code: Code, @@ -209,7 +209,7 @@ func GetCurrency(code string) *Currency { return currencies[code] } -// Formatter returns currency formatter representing +// Formatter returns currency formatter representing. // used currency structure func (c *Currency) Formatter() *Formatter { return &Formatter{ @@ -222,12 +222,12 @@ func (c *Currency) Formatter() *Formatter { } // getDefault represent default currency if currency is not found in currencies list. -// Grapheme and Code fields will be changed by currency code +// Grapheme and Code fields will be changed by currency code. func (c *Currency) getDefault() *Currency { return &Currency{Decimal: ".", Thousand: ",", Code: c.Code, Fraction: 2, Grapheme: c.Code, Template: "1$"} } -// get extended currency using currencies list +// get extended currency using currencies list. func (c *Currency) get() *Currency { if curr, ok := currencies[c.Code]; ok { return curr From 0b3107f85dbe8c566d5dd4fcc775b677c2ecb750 Mon Sep 17 00:00:00 2001 From: daniel witz Date: Sun, 12 May 2019 11:20:29 +0300 Subject: [PATCH 06/10] forgot . --- currency.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/currency.go b/currency.go index 762d153..d000930 100644 --- a/currency.go +++ b/currency.go @@ -210,7 +210,7 @@ func GetCurrency(code string) *Currency { } // Formatter returns currency formatter representing. -// used currency structure +// used currency structure. func (c *Currency) Formatter() *Formatter { return &Formatter{ Fraction: c.Fraction, From 14faf6662b1901ed245cf099ec4c9035ae86d637 Mon Sep 17 00:00:00 2001 From: daniel witz Date: Sun, 12 May 2019 11:22:43 +0300 Subject: [PATCH 07/10] delete unnecessary . --- currency.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/currency.go b/currency.go index d000930..6d50cd3 100644 --- a/currency.go +++ b/currency.go @@ -209,7 +209,7 @@ func GetCurrency(code string) *Currency { return currencies[code] } -// Formatter returns currency formatter representing. +// Formatter returns currency formatter representing // used currency structure. func (c *Currency) Formatter() *Formatter { return &Formatter{ From 7e0ac05f984a8c48ac405fbaac9a33ec670a3694 Mon Sep 17 00:00:00 2001 From: daniel witz Date: Wed, 22 May 2019 16:34:26 +0300 Subject: [PATCH 08/10] fix comment in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e39826d..5d7893a 100644 --- a/README.md +++ b/README.md @@ -245,7 +245,7 @@ To format and return Money as a string use `Display()`. ```go money.New(123456789, "EUR").Display() // €1,234,567.89 ``` -To format and return Money as a float64 representing the amount value in the currency's subunit use `AsSubunits()`. +To format and return Money as a float64 representing the amount value in the currency's subunit use `AsMajorUnits()`. ```go money.New(123456789, "EUR").AsMajorUnits() // 1234567.89 From ca1d6848101341b33b36929f033f53a869b14ca2 Mon Sep 17 00:00:00 2001 From: daniel witz Date: Wed, 22 May 2019 17:13:07 +0300 Subject: [PATCH 09/10] change go mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 3b11dab..2bc65b0 100644 --- a/go.mod +++ b/go.mod @@ -1 +1 @@ -module github.com/danielwitz/go-money +module github.com/Rhymond/go-money From 3a5e46ed9767ee25694feca1e4b23dccce6daeaa Mon Sep 17 00:00:00 2001 From: daniel witz Date: Wed, 24 Jul 2019 17:42:19 +0300 Subject: [PATCH 10/10] PR corrections - performance issue in ToMajorUnits --- formatter.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/formatter.go b/formatter.go index 228b2a7..c58c364 100644 --- a/formatter.go +++ b/formatter.go @@ -57,6 +57,10 @@ func (f *Formatter) Format(amount int64) string { // ToMajorUnits returns float64 representing the value in sub units using the currency data func (f *Formatter) ToMajorUnits(amount int64) float64 { + if f.Fraction == 0 { + return float64(amount) + } + return float64(amount) / float64(math.Pow10(f.Fraction)) }