forked from leekchan/accounting
-
Notifications
You must be signed in to change notification settings - Fork 0
/
accounting.go
99 lines (83 loc) · 3.72 KB
/
accounting.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
package accounting
import (
"math/big"
"strings"
)
type Accounting struct {
Symbol string // currency symbol (required)
Precision int // currency precision (decimal places) (optional / default: 0)
Thousand string // thousand separator (optional / default: ,)
Decimal string // decimal separator (optional / default: .)
Format string // simple format string allows control of symbol position (%v = value, %s = symbol) (default: %s%v)
FormatNegative string // format string for negative values (optional / default: strings.Replace(strings.Replace(accounting.Format, "-", "", -1), "%v", "-%v", -1))
FormatZero string // format string for zero values (optional / default: Format)
}
func (accounting *Accounting) init() {
if accounting.Thousand == "" {
accounting.Thousand = ","
}
if accounting.Decimal == "" {
accounting.Decimal = "."
}
if accounting.Format == "" {
accounting.Format = "%s%v"
}
if accounting.FormatNegative == "" {
accounting.FormatNegative = strings.Replace(strings.Replace(accounting.Format, "-", "", -1), "%v", "-%v", -1)
}
if accounting.FormatZero == "" {
accounting.FormatZero = accounting.Format
}
}
func (accounting *Accounting) formatMoneyString(formattedNumber string) string {
var format string
zero := "0"
if accounting.Precision > 0 {
zero += "." + strings.Repeat("0", accounting.Precision)
}
if formattedNumber[0] == '-' {
format = accounting.FormatNegative
formattedNumber = formattedNumber[1:]
} else if formattedNumber == zero {
format = accounting.FormatZero
} else {
format = accounting.Format
}
result := strings.Replace(format, "%s", accounting.Symbol, -1)
result = strings.Replace(result, "%v", formattedNumber, -1)
return result
}
// FormatMoney is a function for formatting numbers as money values,
// with customisable currency symbol, precision (decimal places), and thousand/decimal separators.
// FormatMoney supports various types of value by runtime reflection.
// If you don't need runtime type evaluation, please refer to FormatMoneyInt or FormatMoneyFloat64.
// (supported value types : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, *big.Rat)
func (accounting *Accounting) FormatMoney(value interface{}) string {
accounting.init()
formattedNumber := FormatNumber(value, accounting.Precision, accounting.Thousand, accounting.Decimal)
return accounting.formatMoneyString(formattedNumber)
}
// FormatMoneyInt only supports int type value. It is faster than FormatMoney,
// because it does not do any runtime type evaluation.
func (accounting *Accounting) FormatMoneyInt(value int) string {
accounting.init()
formattedNumber := FormatNumberInt(value, accounting.Precision, accounting.Thousand, accounting.Decimal)
return accounting.formatMoneyString(formattedNumber)
}
// FormatMoneyFloat64 only supports float64 value. It is faster than FormatMoney,
// because it does not do any runtime type evaluation.
// (Caution: Please do not use float64 to count money.
// Floats can have errors when you perform operations on them.
// Using big.Rat is highly recommended.)
func (accounting *Accounting) FormatMoneyFloat64(value float64) string {
accounting.init()
formattedNumber := FormatNumberFloat64(value, accounting.Precision, accounting.Thousand, accounting.Decimal)
return accounting.formatMoneyString(formattedNumber)
}
// FormatMoneyBigRat only supports *big.Rat value. It is faster than FormatMoney,
// because it does not do any runtime type evaluation.
func (accounting *Accounting) FormatMoneyBigRat(value *big.Rat) string {
accounting.init()
formattedNumber := FormatNumberBigRat(value, accounting.Precision, accounting.Thousand, accounting.Decimal)
return accounting.formatMoneyString(formattedNumber)
}