Skip to content

Commit 98a483f

Browse files
authored
Merge pull request #3 from bnkamalesh/fmt-stringer-interface
Fmt stringer interface
2 parents 4a86204 + b8d3a76 commit 98a483f

File tree

4 files changed

+91
-33
lines changed

4 files changed

+91
-33
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
[![awesome-go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go#financial)
1010

1111

12-
## Currency v1.0.0
12+
## Currency v2.0.0
1313

14-
Currency package helps you do currency computations accurately, by avoiding *_peddling_*.
15-
The `Currency` struct holds all the data required to define a currency.
14+
Currency package helps you do currency computations accurately. `Currency` struct holds all the data required to define a currency.
1615

1716
```
1817
type Currency struct {
@@ -29,6 +28,10 @@ type Currency struct {
2928
// FUShare represents the no.of fractional/sub units that make up 1 main unit. e.g. ₹1 = 100 paise
3029
// Number of fractional units that make up 1 unit of the main value
3130
FUShare uint
31+
// PrefixSymbol if true will prefix the symbol when stringified
32+
PrefixSymbol bool
33+
// SuffixSymbol if true will suffix the symbol when stringified
34+
SuffixSymbol bool
3235
}
3336
```
3437

@@ -81,7 +84,7 @@ e.g. ₹1/- (INR 1) is to be divided by 3. There are 2 options of dividing this
8184

8285
### Multiple currency representations
8386

84-
1. `c1.String(prefixSymbol bool)`, returns a string representation of the currency value. Returns string prefixed by its respective symbol if `prefixSymbol` is true
87+
1. `c1.String()`, returns a string representation of the currency value
8588
2. `c1.Float64()`, returns a float64 representation of the currency value
8689

8790
## Benchmarks

currency.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ type Currency struct {
4848
fuDigits int `json:"fuDigits,omitempty"`
4949
// magnitude is the fraction which sets the magnitude required for the rounding function
5050
magnitude float64 `json:"magnitude,omitempty"`
51+
// PrefixSymbol if true will add the symbol as a prefix to the string representation of currency. e.g. ₹1.5
52+
PrefixSymbol bool `json:"alwaysAddPrefix,omitempty"`
53+
// SuffixSymbol if true will add the symbol as a suffix to the string representation of currency. e.g. 1.5₹
54+
SuffixSymbol bool `json:"alwaysAddSuffix,omitempty"`
5155
}
5256

5357
// New returns a new instance of currency.
@@ -190,8 +194,7 @@ func (c *Currency) Float64() float64 {
190194
return float64(c.Main) + (float64(frac) / float64(c.FUShare))
191195
}
192196

193-
// String returns the currency represented as string.
194-
func (c *Currency) String(prefixSymbol bool) string {
197+
func (c *Currency) StringWithoutSymbols() string {
195198
frc := c.Fractional
196199
if c.Fractional < 0 {
197200
frc = -frc
@@ -209,24 +212,35 @@ func (c *Currency) String(prefixSymbol bool) string {
209212
if c.Fractional < 0 {
210213
str = "-" + str
211214
}
215+
return str
216+
}
212217

213-
if prefixSymbol {
218+
// String returns the currency represented as string.
219+
func (c *Currency) String() string {
220+
str := c.StringWithoutSymbols()
221+
222+
if c.PrefixSymbol {
214223
if c.Fractional < 0 || c.Main < 0 {
215224
str = strings.Replace(str, "-", "-"+c.Symbol, 1)
216225
} else {
217226
str = c.Symbol + str
218227
}
219228
}
220229

230+
if c.SuffixSymbol {
231+
str = str + c.Symbol
232+
}
233+
221234
return str
222235
}
223236

224237
func (c *Currency) Format(s fmt.State, verb rune) {
225238
switch verb {
226-
// 's' verb would produce the full currency string along with its symbol. equivalent to c.String(true)
227-
case 's':
239+
// 's' verb would produce the full currency string along with its symbol. equivalent to c.String()
240+
// 'v' - only once you add this does the fmt.Stringer seem to work, otherwise it's always printing blank
241+
case 's', 'v':
228242
{
229-
_, _ = io.WriteString(s, c.String(true))
243+
_, _ = io.WriteString(s, c.String())
230244
}
231245
// 'd' verb would produce the main integer part of the currency, without the symbol
232246
case 'd':
@@ -240,10 +254,10 @@ func (c *Currency) Format(s fmt.State, verb rune) {
240254
main := strconv.Itoa(c.Fractional)
241255
_, _ = io.WriteString(s, main)
242256
}
243-
// 'f' verb would produce the full currency string without its symbol. equivalent to c.String(false)
257+
// 'f' verb would produce the full currency string without its symbol. equivalent to c.StringWithoutSymbols()
244258
case 'f':
245259
{
246-
_, _ = io.WriteString(s, c.String(false))
260+
_, _ = io.WriteString(s, c.StringWithoutSymbols())
247261
}
248262
// 'y' verb would produce the currency symbol alone
249263
case 'y':

currency_test.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ func TestNew(t *testing.T) {
9494
t.Fail()
9595
}
9696

97-
str := cur.String(true)
97+
cur.PrefixSymbol = true
98+
str := cur.String()
9899
if str != nT.out.str {
99100
t.Log("Expected:", nT.out.str, "got:", str)
100101
t.Fail()
@@ -137,7 +138,8 @@ func TestNewFractional(t *testing.T) {
137138
t.Fail()
138139
}
139140

140-
str := cur.String(true)
141+
cur.PrefixSymbol = true
142+
str := cur.String()
141143
if str != nT.out.str {
142144
t.Log("Expected:", nT.out.str, "got:", str)
143145
t.Fail()
@@ -179,7 +181,8 @@ func TestParseStr(t *testing.T) {
179181
t.Fail()
180182
}
181183

182-
str := cur.String(true)
184+
cur.PrefixSymbol = true
185+
str := cur.String()
183186
if str != nT.out.str {
184187
t.Log("Expected:", nT.out.str, "got:", str)
185188
t.Fail()
@@ -221,7 +224,8 @@ func TestParseFloat64(t *testing.T) {
221224
t.Fail()
222225
}
223226

224-
str := cur.String(true)
227+
cur.PrefixSymbol = true
228+
str := cur.String()
225229
if str != nT.out.str {
226230
t.Log("Expected:", nT.out.str, "got:", str)
227231
t.Fail()
@@ -245,11 +249,29 @@ func TestFormat(t *testing.T) {
245249
list := []struct {
246250
Verb string
247251
Expected string
252+
Prefix bool
253+
Suffix bool
248254
}{
249255
{
250256
Verb: "s",
257+
Expected: "12.75",
258+
},
259+
{
260+
Verb: "s",
261+
Prefix: true,
251262
Expected: "₹12.75",
252263
},
264+
{
265+
Verb: "s",
266+
Suffix: true,
267+
Expected: "12.75₹",
268+
},
269+
{
270+
Verb: "s",
271+
Suffix: true,
272+
Prefix: true,
273+
Expected: "₹12.75₹",
274+
},
253275
{
254276
Verb: "d",
255277
Expected: "12",
@@ -268,6 +290,9 @@ func TestFormat(t *testing.T) {
268290
},
269291
}
270292
for _, l := range list {
293+
c.PrefixSymbol = l.Prefix
294+
c.SuffixSymbol = l.Suffix
295+
271296
formatstr := "%" + l.Verb
272297
str := fmt.Sprintf(formatstr, c)
273298
if str != l.Expected {
@@ -302,15 +327,16 @@ func BenchmarkParseString(t *testing.B) {
302327

303328
func BenchmarkString(t *testing.B) {
304329
cur1, _ := New(10, 5, "INR", "₹", "paise", 100)
330+
cur1.PrefixSymbol = true
305331
for i := 0; i < t.N; i++ {
306-
cur1.String(true)
332+
cur1.String()
307333
}
308334
}
309335

310336
func BenchmarkStringNoPrefix(t *testing.B) {
311337
cur1, _ := New(10, 5, "INR", "₹", "paise", 100)
312338
for i := 0; i < t.N; i++ {
313-
cur1.String(false)
339+
cur1.StringWithoutSymbols()
314340
}
315341
}
316342

operations_test.go

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ func TestUpdateWithFractional(t *testing.T) {
2020
t.Fail()
2121
}
2222

23-
s := cur.String(true)
23+
cur.PrefixSymbol = true
24+
s := cur.String()
2425
if s != "₹10.05" {
2526
t.Log("Expected ₹10.05, got:", s)
2627
t.Fail()
@@ -59,7 +60,8 @@ func TestAdd(t *testing.T) {
5960
t.Fail()
6061
}
6162

62-
str := cur1.String(true)
63+
cur1.PrefixSymbol = true
64+
str := cur1.String()
6365
if str != "₹21.98" {
6466
t.Log("Expected ₹21.98, got:", str)
6567
t.Fail()
@@ -98,7 +100,8 @@ func TestAdd2(t *testing.T) {
98100
t.Fail()
99101
}
100102

101-
str := cur1.String(true)
103+
cur1.PrefixSymbol = true
104+
str := cur1.String()
102105
if str != "₹0.00" {
103106
t.Log("Expected ₹0.00, got:", str)
104107
t.Fail()
@@ -136,7 +139,8 @@ func TestAdd3(t *testing.T) {
136139
t.Fail()
137140
}
138141

139-
str := cur1.String(true)
142+
cur1.PrefixSymbol = true
143+
str := cur1.String()
140144
if str != "-₹20.50" {
141145
t.Log("Expected -₹20.50, got:", str)
142146
t.Fail()
@@ -168,7 +172,8 @@ func TestAddInt(t *testing.T) {
168172
t.Fail()
169173
}
170174

171-
str := cur.String(true)
175+
cur.PrefixSymbol = true
176+
str := cur.String()
172177
if str != "₹21.09" {
173178
t.Log("Expected:", "₹21.09", "got:", str)
174179
t.Fail()
@@ -207,7 +212,8 @@ func TestSubtract(t *testing.T) {
207212
t.Fail()
208213
}
209214

210-
str := cur1.String(true)
215+
cur1.PrefixSymbol = true
216+
str := cur1.String()
211217
if str != "-₹1.00" {
212218
t.Log("Expected -₹1.00, got:", str)
213219
t.Fail()
@@ -246,7 +252,8 @@ func TestSub2(t *testing.T) {
246252
t.Fail()
247253
}
248254

249-
str := cur1.String(true)
255+
cur1.PrefixSymbol = true
256+
str := cur1.String()
250257
if str != "₹4.70" {
251258
t.Log("Expected ₹4.70, got:", str)
252259
t.Fail()
@@ -278,7 +285,8 @@ func TestSubtractInt(t *testing.T) {
278285
t.Fail()
279286
}
280287

281-
str := cur.String(true)
288+
cur.PrefixSymbol = true
289+
str := cur.String()
282290
if str != "-₹0.09" {
283291
t.Log("Expected:", "-₹0.09", "got:", str)
284292
t.Fail()
@@ -310,7 +318,8 @@ func TestMultiply(t *testing.T) {
310318
t.Fail()
311319
}
312320

313-
str := cur1.String(true)
321+
cur1.PrefixSymbol = true
322+
str := cur1.String()
314323
if str != "₹52.50" {
315324
t.Log("Expected ₹52.50, got:", str)
316325
t.Fail()
@@ -342,7 +351,8 @@ func TestMultiplyFloat64(t *testing.T) {
342351
t.Fail()
343352
}
344353

345-
str := cur1.String(true)
354+
cur1.PrefixSymbol = true
355+
str := cur1.String()
346356
if str != "₹11.03" {
347357
t.Log("Expected ₹11.03, got:", str)
348358
t.Fail()
@@ -374,7 +384,8 @@ func TestPercent(t *testing.T) {
374384
t.Fail()
375385
}
376386

377-
str := cur2.String(true)
387+
cur2.PrefixSymbol = true
388+
str := cur2.String()
378389
if str != "₹0.55" {
379390
t.Log("Expected ₹0.55, got:", str)
380391
t.Fail()
@@ -400,7 +411,8 @@ func TestDivideRetain(t *testing.T) {
400411
t.Fail()
401412
}
402413

403-
for _, split := range splits {
414+
for idx := range splits {
415+
split := splits[idx]
404416
if split.Main != 0 {
405417
t.Log("Expected", 0, "got:", split.Main)
406418
t.Fail()
@@ -411,7 +423,8 @@ func TestDivideRetain(t *testing.T) {
411423
t.Fail()
412424
}
413425

414-
str := split.String(true)
426+
split.PrefixSymbol = true
427+
str := split.String()
415428
if str != "₹0.33" {
416429
t.Log("Expected:", "₹0.33", "got:", str)
417430
t.Fail()
@@ -443,7 +456,8 @@ func TestDivideNoRetain(t *testing.T) {
443456
t.Fail()
444457
}
445458

446-
for _, split := range splits {
459+
for idx := range splits {
460+
split := splits[idx]
447461
if split.Main != 0 {
448462
t.Log("Expected", 0, "got:", split.Main)
449463
t.Fail()
@@ -454,7 +468,8 @@ func TestDivideNoRetain(t *testing.T) {
454468
t.Fail()
455469
}
456470

457-
str := split.String(true)
471+
split.PrefixSymbol = true
472+
str := split.String()
458473
if str != "₹0.33" && str != "₹0.34" {
459474
t.Log("Expected:", "₹0.33 or ₹0.34", "got:", str)
460475
t.Fail()

0 commit comments

Comments
 (0)