Skip to content

Commit

Permalink
Add protomoney.Fmt().
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Feb 8, 2022
1 parent 8b9f945 commit 4330054
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 3 deletions.
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,24 @@ The format is based on [Keep a Changelog], and this project adheres to
[Semantic Versioning].

<!-- references -->
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html

[keep a changelog]: https://keepachangelog.com/en/1.0.0/
[semantic versioning]: https://semver.org/spec/v2.0.0.html

## [Unreleased]

### Added

- Add `protomoney.Fmt()`
- Add original Google `money.proto` file to `protomoney` package

## [0.1.0] - 2021-06-14

- Initial release

<!-- references -->
[Unreleased]: https://github.com/dogmatiq/dosh

[unreleased]: https://github.com/dogmatiq/dosh
[0.1.0]: https://github.com/dogmatiq/dogma/releases/tag/v0.1.0

<!-- version template
Expand Down
40 changes: 40 additions & 0 deletions protomoney/format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package protomoney

import (
"fmt"
"math/big"

"google.golang.org/genproto/googleapis/type/money"
)

// Fmt wraps a money value in a formatter allows it to be formatted using
// standard fmt.Printf() verbs.
func Fmt(m *money.Money) fmt.Formatter {
return formatter{m}
}

type formatter struct {
value *money.Money
}

func (f formatter) Format(st fmt.State, verb rune) {
m := normalize(f.value)

switch verb {
case 'f', 'F', // decimal notation
'e', 'E', // scientific notation
'g', 'G', // decimal notation, or scientific for large exponents
'v': // "default" format
// This is a subset of the verbs are supported by big.Float.Format().

s := fmt.Sprintf("%d.%09d", m.GetUnits(), m.GetNanos())
f := &big.Float{}
f.SetString(s)

fmt.Fprintf(st, "%s ", m.GetCurrencyCode())
f.Format(st, verb)

default:
fmt.Fprintf(st, "%%!%c(*money.Money=%s)", verb, f.value.String())
}
}
43 changes: 43 additions & 0 deletions protomoney/format_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package protomoney_test

import (
"fmt"

. "github.com/dogmatiq/dosh/protomoney"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"google.golang.org/genproto/googleapis/type/money"
)

func ExampleFmt() {
m := &money.Money{
CurrencyCode: "XYZ",
Units: 10,
Nanos: 129000000,
}

fmt.Printf("%.2f\n", Fmt(m))
// Output: XYZ 10.13
}

var _ = Describe("func Fmt()", func() {
It("returns a formatted representation of the amount", func() {
m := &money.Money{
CurrencyCode: "XYZ",
Units: 10,
Nanos: 129000000,
}
s := fmt.Sprintf("%0.2f", Fmt(m))
Expect(s).To(Equal("XYZ 10.13"))
})

It("returns a descriptive string if used with an unsupported verb", func() {
m := &money.Money{
CurrencyCode: "XYZ",
Units: 10,
Nanos: 129000000,
}
s := fmt.Sprintf("%d", Fmt(m))
Expect(s).To(Equal("%!d(*money.Money=" + m.String() + ")"))
})
})

0 comments on commit 4330054

Please sign in to comment.