-
Notifications
You must be signed in to change notification settings - Fork 0
/
currency.go
106 lines (87 loc) · 2.17 KB
/
currency.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package currency
import (
// TODO remove this dependency
"fmt"
"strconv"
"strings"
)
// Currency represents money currency information required for formatting.
type Currency struct {
Code string
NumericCode string
Fraction int
Grapheme string
Template string
Decimal string
Thousand string
}
// Get returns the currency given the code.
func Get(code string) *Currency {
return currencies.CurrencyByCode(code)
}
// GetOrDefault returns the currency given the code or default currency if not found.
func GetOrDefault(currencyCode string) *Currency {
code := strings.ToUpper(currencyCode)
currency := Get(code)
if currency == nil {
currency = &Currency{
Code: code,
Template: "$1",
Grapheme: code,
Decimal: ".",
Thousand: ",",
Fraction: 0,
}
currencies.Add(currency) // Cache the currency
return currency
}
return currency
}
// IsValid returns true if the currency code is one of the registered currencies.
func IsValid(currencyCode string) bool {
return Get(currencyCode) != nil
}
// Check returns an error if the currency code is not one of the registered currencies.
func Check(currencyCode string) error {
if !IsValid(currencyCode) {
return fmt.Errorf("invalid currency code: %s", currencyCode)
}
return nil
}
func (c *Currency) Equals(oc *Currency) bool {
if c == nil || oc == nil {
return c == oc
}
return c.Code == oc.Code
}
func (c *Currency) Format(amount int64) string { // TODO improve, use better formatter
if c == nil {
return GetOrDefault("").Format(amount)
}
// Work with absolute amount value
sa := strconv.FormatInt(abs(amount), 10)
if len(sa) <= c.Fraction {
sa = strings.Repeat("0", c.Fraction-len(sa)+1) + sa
}
if c.Thousand != "" {
for i := len(sa) - c.Fraction - 3; i > 0; i -= 3 {
sa = sa[:i] + c.Thousand + sa[i:]
}
}
if c.Fraction > 0 {
sa = sa[:len(sa)-c.Fraction] + c.Decimal + sa[len(sa)-c.Fraction:]
}
sa = strings.Replace(c.Template, "1", sa, 1)
sa = strings.Replace(sa, "$", c.Grapheme, 1)
// Add minus sign for negative amount.
if amount < 0 {
sa = "-" + sa
}
return sa
}
func abs(amount int64) int64 {
if amount < 0 {
return -amount
}
return amount
}