-
Notifications
You must be signed in to change notification settings - Fork 0
/
amount.go
110 lines (97 loc) · 2.19 KB
/
amount.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
107
108
109
110
package money
import (
"encoding/xml"
"io"
"math"
"strconv"
"strings"
)
type Amount int
func (amount Amount) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
elem := xml.StartElement{
Name: xml.Name{Space: "", Local: start.Name.Local},
Attr: []xml.Attr{},
}
if err := e.EncodeElement(amount.String(), elem); err != nil {
return err
}
return nil
}
func (amount *Amount) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
token, err := d.Token()
if err == io.EOF { // found end of element
break
}
if err != nil {
return err
}
switch element := token.(type) {
case xml.CharData:
a, err := Parse(string(element))
if err != nil {
return err
}
*amount = a
}
}
return nil
}
func Parse(amountStr string) (Amount, error) {
// Make sure it is a valid float first
_, err := strconv.ParseFloat(amountStr, 64)
if err != nil {
return Amount(0), err
}
index := strings.Index(amountStr, ".")
pow := 2
amountStrLen := len(amountStr)
if index != -1 {
amountStr = strings.Replace(amountStr, ".", "", 1)
index = amountStrLen - index
pow = 3 - index
}
a, err := strconv.Atoi(amountStr)
if err != nil {
return Amount(0), err
}
a = int(float64(a) * (math.Pow(float64(10), float64(pow))))
amount := (Amount)(a)
return amount, nil
}
func (amount Amount) MarshalJSON() ([]byte, error) {
return []byte(amount.String()), nil
}
func (amount *Amount) UnmarshalJSON(bytes []byte) error {
a, err := Parse(string(bytes))
if err != nil {
return err
}
*amount = a
return nil
}
func (amount *Amount) Float() float64 {
amountInt := int(*amount)
return float64(amountInt) / 100
}
// NOTE: this function truncates decimals
func (amount *Amount) Int() int {
amountInt := int(*amount)
return amountInt / 100
}
func (amount *Amount) String() string {
// stay close to how Go prints float64(0.00)
if int(*amount) == 0 {
return "0"
}
amountStr := strconv.Itoa(int(*amount))
length := len(amountStr)
// Add left zeros to have format "0.01" and "0.12"
for i := 0; i < 3-length; i += 1 {
amountStr = "0" + amountStr
}
length = len(amountStr)
decimals := amountStr[length-2:]
integers := amountStr[:length-2]
return integers + "." + decimals
}