This repository has been archived by the owner on Jul 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcurrency_converter.go
146 lines (127 loc) · 3.88 KB
/
currency_converter.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// The package provides methods for converting amounts between currencies. The
// exchange rates are provided by the ECB (http://www.ecb.europa.eu/).
package currency
import (
"errors"
"fmt"
"time"
)
const (
eur = "EUR"
unknown = "Unknown currency: %s"
)
// The CurrencyConverter struct holds the data that enables the conversion.
// Upon creation the data is fetched from the ECB and parsed into the struct.
type CurrencyConverter struct {
lastUpdate time.Time
date time.Time
currencies map[string]float64
singleConverters []*SingleCurrencyConverter
}
// Creates a new converter by fetching the required data from the ECB.
func NewConverter() (*CurrencyConverter, error) {
currencyTime, currencies, err := parseEcbData()
if err != nil {
return nil, err
}
converter := CurrencyConverter{date: currencyTime, currencies: currencies, lastUpdate: time.Now()}
return &converter, nil
}
func (c *CurrencyConverter) GetCurrencyDate() time.Time {
return c.date
}
func (c *CurrencyConverter) GetCurrencies() []string {
currencies := make([]string, len(c.currencies))
index := 0
for currency, _ := range c.currencies {
currencies[index] = currency
index++
}
return currencies
}
// Returns true if the currency is known by the converter.
func (c *CurrencyConverter) HasCurrency(currency string) bool {
_, ok := c.currencies[currency]
return ok
}
func (c *CurrencyConverter) Age() float64 {
delta := time.Now().Sub(c.lastUpdate)
return delta.Seconds()
}
func (c *CurrencyConverter) CurrencyAge() float64 {
delta := time.Now().Sub(c.date)
return delta.Seconds()
}
// Returns true if the currencies stores are so old they should be renewed from
// the ECB server.
func (c *CurrencyConverter) ShouldRenew(seconds float64) bool {
if c.Age() >= seconds {
return true
}
return false
}
// Renew the currency data by fetching the from the ECB server. This will
// also update all the SingleCurrencyConverter created from this CurrencyConverter.
func (c *CurrencyConverter) Renew() error {
date, currencies, err := parseEcbData()
if err != nil {
return err
} else {
c.lastUpdate = time.Now()
c.date = date
c.currencies = currencies
for _, s := range c.singleConverters {
s.renew(c)
}
return nil
}
}
// Converts an amount between two currencies.
func (c *CurrencyConverter) Convert(amount float64, from string, to string) (float64, error) {
fromRate, fromOk := c.currencies[from]
if !fromOk {
return 0, errors.New(fmt.Sprintf(unknown, from))
}
toRate, toOk := c.currencies[to]
if !toOk {
return 0, errors.New(fmt.Sprintf(unknown, to))
}
return amount / fromRate * toRate, nil
}
// Converts a slice of amounts from one currency to another.
func (c *CurrencyConverter) MultiConvert(amounts []float64, from, to string) ([]float64, error) {
convertedAmounts := make([]float64, len(amounts))
var e error
for i, amount := range amounts {
converted, err := c.Convert(amount, from, to)
if err != nil {
e = err
}
convertedAmounts[i] = converted
}
return convertedAmounts, e
}
// Creates a SingleCurrencyConverter that easilly translates amounts between
// two fixed currencies.
func (c *CurrencyConverter) GetSingleCurrencyConverter(from, to string) (*SingleCurrencyConverter, error) {
fromRate, fromOk := c.currencies[from]
if !fromOk {
return nil, errors.New(fmt.Sprintf(unknown, from))
}
toRate, toOk := c.currencies[to]
if !toOk {
return nil, errors.New(fmt.Sprintf(unknown, to))
}
converter := SingleCurrencyConverter{date: c.date, from: from, to: to, fromRate: fromRate, toRate: toRate}
c.singleConverters = append(c.singleConverters, &converter)
return &converter, nil
}
func (c *CurrencyConverter) GetCurrencyInformation(currency string) (longName string, country string, err error) {
if info, ok := currencyData[currency]; ok {
longName = info.LongName
country = info.Country
} else {
err = errors.New(fmt.Sprintf(unknown, currency))
}
return
}