aboutsummaryrefslogtreecommitdiff
path: root/backend/internal/utils
diff options
context:
space:
mode:
authorGravatar Anshul Gupta <ansg191@anshulg.com> 2024-08-05 18:55:10 -0700
committerGravatar Anshul Gupta <ansg191@anshulg.com> 2024-08-05 18:55:19 -0700
commitb96fcd1a54a46a95f98467b49a051564bc21c23c (patch)
tree93caeeb05f8d6310e241095608ea2428c749b18c /backend/internal/utils
downloadibd-trader-b96fcd1a54a46a95f98467b49a051564bc21c23c.tar.gz
ibd-trader-b96fcd1a54a46a95f98467b49a051564bc21c23c.tar.zst
ibd-trader-b96fcd1a54a46a95f98467b49a051564bc21c23c.zip
Initial Commit
Diffstat (limited to 'backend/internal/utils')
-rw-r--r--backend/internal/utils/money.go99
-rw-r--r--backend/internal/utils/money_test.go106
2 files changed, 205 insertions, 0 deletions
diff --git a/backend/internal/utils/money.go b/backend/internal/utils/money.go
new file mode 100644
index 0000000..2dc2286
--- /dev/null
+++ b/backend/internal/utils/money.go
@@ -0,0 +1,99 @@
+package utils
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/Rhymond/go-money"
+)
+
+// supported currencies
+var currencies = money.Currencies{
+ "USD": money.GetCurrency(money.USD),
+ "EUR": money.GetCurrency(money.EUR),
+ "GBP": money.GetCurrency(money.GBP),
+ "JPY": money.GetCurrency(money.JPY),
+ "CNY": money.GetCurrency(money.CNY),
+}
+
+func ParseMoney(s string) (*money.Money, error) {
+ for _, c := range currencies {
+ numPart, ok := isCurrency(s, c)
+ if !ok {
+ continue
+ }
+
+ // Parse the number part
+ num, err := strconv.ParseUint(numPart, 10, 64)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse number: %w", err)
+ }
+
+ return money.New(int64(num), c.Code), nil
+ }
+ return nil, fmt.Errorf("matching currency not found")
+}
+
+func isCurrency(s string, c *money.Currency) (string, bool) {
+ var numPart string
+ for _, tp := range c.Template {
+ switch tp {
+ case '$':
+ // There should be a matching grapheme in the s at this position
+ remaining, ok := strings.CutPrefix(s, c.Grapheme)
+ if !ok {
+ return "", false
+ }
+ s = remaining
+ case '1':
+ // There should be a number, thousands, or decimal separator in the s at this position
+ // Number of expected decimal places
+ decimalFound := -1
+ // Read from string until a non-number, non-thousands, non-decimal, or EOF is found
+ for len(s) > 0 && (string(s[0]) == c.Thousand || string(s[0]) == c.Decimal || '0' <= s[0] && s[0] <= '9') {
+ // If the character is a number
+ if '0' <= s[0] && s[0] <= '9' {
+ // If we've hit decimal limit, break
+ if decimalFound == 0 {
+ break
+ }
+ // add the number to the numPart
+ numPart += string(s[0])
+ // Decrement the decimal count
+ // If the decimal has been found, `decimalFound` is positive
+ // If the decimal hasn't been found, `decimalFound` is negative, and decrementing it does nothing
+ decimalFound--
+ }
+ // If decimal has been found (>= 0) and the character is a thousand separator or decimal separator,
+ // then the number is invalid
+ if decimalFound >= 0 && (string(s[0]) == c.Thousand || string(s[0]) == c.Decimal) {
+ return "", false
+ }
+ // If the character is a decimal separator, set `decimalFound` to the number of
+ // expected decimal places for the currency
+ if string(s[0]) == c.Decimal {
+ decimalFound = c.Fraction
+ }
+ // Move to the next character
+ s = s[1:]
+ }
+ if decimalFound > 0 {
+ // If there should be more decimal places, add them
+ numPart += strings.Repeat("0", decimalFound)
+ } else if decimalFound < 0 {
+ // If no decimal was found, add the expected number of decimal places
+ numPart += strings.Repeat("0", c.Fraction)
+ }
+ case ' ':
+ // There should be a space in the s at this position
+ if len(s) == 0 || s[0] != ' ' {
+ return "", false
+ }
+ s = s[1:]
+ default:
+ panic(fmt.Sprintf("unsupported template character: %c", tp))
+ }
+ }
+ return numPart, true
+}
diff --git a/backend/internal/utils/money_test.go b/backend/internal/utils/money_test.go
new file mode 100644
index 0000000..27ace06
--- /dev/null
+++ b/backend/internal/utils/money_test.go
@@ -0,0 +1,106 @@
+package utils
+
+import (
+ "testing"
+
+ "github.com/Rhymond/go-money"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestParseMoney(t *testing.T) {
+ tests := []struct {
+ name string
+ input string
+ want *money.Money
+ }{
+ {
+ name: "en-US int no comma",
+ input: "$123",
+ want: money.New(12300, money.USD),
+ },
+ {
+ name: "en-US int comma",
+ input: "$1,123",
+ want: money.New(112300, money.USD),
+ },
+ {
+ name: "en-US decimal comma",
+ input: "$1,123.45",
+ want: money.New(112345, money.USD),
+ },
+ {
+ name: "zh-CN decimal comma",
+ input: "1,234.56 \u5143",
+ want: money.New(123456, money.CNY),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ m, err := ParseMoney(tt.input)
+ assert.NoError(t, err)
+ assert.Equal(t, tt.want, m)
+ })
+ }
+}
+
+func Test_isCurrency(t *testing.T) {
+ tests := []struct {
+ name string
+ input string
+ currency string
+ numPart string
+ ok bool
+ }{
+ {
+ name: "en-US int no comma",
+ input: "$123",
+ currency: money.USD,
+ numPart: "12300",
+ ok: true,
+ },
+ {
+ name: "en-US int comma",
+ input: "$1,123",
+ currency: money.USD,
+ numPart: "112300",
+ ok: true,
+ },
+ {
+ name: "en-US decimal comma",
+ input: "$1,123.45",
+ currency: money.USD,
+ numPart: "112345",
+ ok: true,
+ },
+ {
+ name: "en-US 1 decimal comma",
+ input: "$1,123.5",
+ currency: money.USD,
+ numPart: "112350",
+ ok: true,
+ },
+ {
+ name: "en-US no grapheme",
+ input: "1,234.56",
+ currency: money.USD,
+ numPart: "",
+ ok: false,
+ },
+ {
+ name: "zh-CN decimal comma",
+ input: "1,234.56 \u5143",
+ currency: money.CNY,
+ numPart: "123456",
+ ok: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := money.GetCurrency(tt.currency)
+ numPart, ok := isCurrency(tt.input, c)
+ assert.Equal(t, tt.ok, ok)
+ assert.Equal(t, tt.numPart, numPart)
+ })
+ }
+}
ent-api-2'>wip-component-api-2 Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/packages/webapi/test/imagedata.js (unfollow)
AgeCommit message (Collapse)AuthorFilesLines
2022-04-10attempt to fix the 'no commits' bug in changesetGravatar Fred K. Schott 1-1/+1
2022-04-10revert releaseGravatar Fred K. Schott 76-225/+329
2022-04-10Update astro changelogGravatar Fred K. Schott 1-29/+0
2022-04-11[ci] formatGravatar FredKSchott 3-34/+34
2022-04-10[ci] release (#3060)Gravatar github-actions[bot] 76-363/+288
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-04-10update changesetGravatar Fred K. Schott 1-1/+0
2022-04-10update changesetGravatar Fred K. Schott 1-1/+1
2022-04-10update lockfile (#3059)Gravatar Fred K. Schott 29-914/+698
2022-04-10correct changesetsGravatar Fred K. Schott 3-3/+11
2022-04-10chore: webapi test now use chai (#3048)Gravatar Juan Martín Seery 16-814/+539
2022-04-10update test names containing spacesGravatar Fred K. Schott 26-17/+17
2022-04-11[ci] formatGravatar FredKSchott 2-8/+7
2022-04-10Fix SSR static build public file copying. fixes #3016 (#3037)Gravatar Steve Lee 8-5/+48
* Fix SSR static build public file copying * chore: update lockfile * remove dirname and use URL constructor * Cleanup test and actually test what it says it tests Co-authored-by: Nate Moore <nate@skypack.dev>
2022-04-10fix our weird beta release issues (#3031)Gravatar Fred K. Schott 4-6/+116
2022-04-10update tailwind integration readmeGravatar Fred K. Schott 2-9/+38
2022-04-10Fixed MD Lint issues (#3038)Gravatar Rafid Muhymin Wafi 1-12/+11