Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v1.3.0 [2025-05-06]
_What's new?_
* Add `ToHumanisedString` func to make values more readable.

## v1.2.0 [2025-03-17]
_Bug fixes_
* Fix `ParseTime` helper to return `time.Time` instead of `*time.Time`. ([#95](https://github.com/turbot/go-kit/issues/95))
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.5.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
Expand Down
58 changes: 58 additions & 0 deletions types/convert_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/btubbs/datetime"
"github.com/dustin/go-humanize"
"github.com/mitchellh/mapstructure"
)

Expand Down Expand Up @@ -105,6 +106,63 @@ func ToString(x interface{}) string {
return fmt.Sprintf("%+v", x)
}

// ToHumanisedString converts most types value to a humanised string
func ToHumanisedString(x interface{}) string {
switch v := x.(type) {
case *int8:
return humanize.Comma(int64(Int8Value(v)))
case *int16:
return humanize.Comma(int64(Int16Value(v)))
case *int32:
return humanize.Comma(int64(Int32Value(v)))
case *int64:
return humanize.Comma(Int64Value(v))
case *int:
return humanize.Comma(int64(IntValue(v)))
case *uint8:
return humanize.Comma(int64(Uint8Value(v)))
case *uint16:
return humanize.Comma(int64(Uint16Value(v)))
case *uint32:
return humanize.Comma(int64(Uint32Value(v)))
case *uint64:
return humanize.Comma(int64(Uint64Value(v)))
case *uint:
return humanize.Comma(int64(UintValue(v)))
case *float32:
return humanize.Commaf(float64(Float32Value(v)))
case *float64:
return humanize.Commaf(Float64Value(v))
case float64:
return humanize.Commaf(v)
case float32:
return humanize.Commaf(float64(v))
case int8:
return humanize.Comma(int64(v))
case int16:
return humanize.Comma(int64(v))
case int32:
return humanize.Comma(int64(v))
case int:
return humanize.Comma(int64(v))
case int64:
return humanize.Comma(v)
case uint8:
return humanize.Comma(int64(v))
case uint16:
return humanize.Comma(int64(v))
case uint32:
return humanize.Comma(int64(v))
case uint64:
return humanize.Comma(int64(v))
case uint:
return humanize.Comma(int64(v))
default:
// call ToString to get a string representation of the value
return ToString(v)
}
}

// FloatToString converts interface to a string representation of a float.
// Panic if interface is not convertible or parseable as a float
func FloatToString(x interface{}) string {
Expand Down
179 changes: 120 additions & 59 deletions types/convert_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ type numberConversionInput struct {
}

var numberConversionInputData = numberConversionInput{
int64(100),
int32(100),
int32(100),
int64(1234567),
int32(1234567),
int32(1234567),
int8(100),
int(100),
uint64(100),
uint32(100),
uint16(100),
int(1234567),
uint64(1234567),
uint32(1234567),
uint16(12345),
uint8(100),
uint(100),
uint(1234567),
byte(100),
float64(100.12345678),
float32(100.1234),
float64(1234.12345678),
float32(1234.1234),
true,
false,
"true",
Expand All @@ -77,13 +77,13 @@ var numberConversionInputData = numberConversionInput{
"false",
"off",
"disabled",
"100",
"100.12345678",
"1234567",
"1234567.12345678",
"invalid",
map[string]string{
"a": "b",
},
1,
1234567,
structType{"A"},
enumType_a,
}
Expand All @@ -104,35 +104,42 @@ func executeToStringTest(t *testing.T, test numberConversionTest, conv toStringF
}

var testCasesToString = []numberConversionTest{
{"int64", numberConversionInputData._int64, "100"},
{"int32", numberConversionInputData._int32, "100"},
{"int16", numberConversionInputData._int16, "100"},
{"int64", numberConversionInputData._int64, "1234567"},
{"int32", numberConversionInputData._int32, "1234567"},
{"int16", numberConversionInputData._int16, "1234567"},
{"int8", numberConversionInputData._int8, "100"},
{"int", numberConversionInputData._int, "100"},
{"uint64", numberConversionInputData._uint64, "100"},
{"uint32", numberConversionInputData._uint32, "100"},
{"uint16", numberConversionInputData._uint16, "100"},
{"int", numberConversionInputData._int, "1234567"},
{"uint64", numberConversionInputData._uint64, "1234567"},
{"uint32", numberConversionInputData._uint32, "1234567"},
{"uint16", numberConversionInputData._uint16, "12345"},
{"uint8", numberConversionInputData._uint8, "100"},
{"uint", numberConversionInputData._uint, "100"},
{"uint", numberConversionInputData._uint, "1234567"},
{"byte", numberConversionInputData._byte, "100"},
{"float64", numberConversionInputData._float64, "100.12345678"},
{"float32", numberConversionInputData._float32, "100.1234"},
{"*int64", &numberConversionInputData._int64, "100"},
{"*int32", &numberConversionInputData._int32, "100"},
{"*int16", &numberConversionInputData._int16, "100"},
{"float64", numberConversionInputData._float64, "1234.12345678"},
{"float32", numberConversionInputData._float32, "1234.1234"},
{"*int64", &numberConversionInputData._int64, "1234567"},
{"*int32", &numberConversionInputData._int32, "1234567"},
{"*int16", &numberConversionInputData._int16, "1234567"},
{"*int8", &numberConversionInputData._int8, "100"},
{"*int", &numberConversionInputData._int, "100"},
{"*uint64", &numberConversionInputData._uint64, "100"},
{"*uint32", &numberConversionInputData._uint32, "100"},
{"*uint16", &numberConversionInputData._uint16, "100"},
{"*int", &numberConversionInputData._int, "1234567"},
{"*uint64", &numberConversionInputData._uint64, "1234567"},
{"*uint32", &numberConversionInputData._uint32, "1234567"},
{"*uint16", &numberConversionInputData._uint16, "12345"},
{"*uint8", &numberConversionInputData._uint8, "100"},
{"*uint", &numberConversionInputData._uint, "100"},
{"*uint", &numberConversionInputData._uint, "1234567"},
{"*byte", &numberConversionInputData._byte, "100"},
{"*float64 ", &numberConversionInputData._float64, "100.12345678"},
{"*float32", &numberConversionInputData._float32, "100.1234"},
{"*float64", &numberConversionInputData._float64, "1234.12345678"},
{"*float32", &numberConversionInputData._float32, "1234.1234"},
{"map", numberConversionInputData._map, "map[a:b]"},
{"struct", numberConversionInputData._struct, "{a:A}"},
{"enum", numberConversionInputData._enum, "a-val"},

// Nil pointer cases
{"nil *string", (*string)(nil), ""},
{"nil *bool", (*bool)(nil), "<nil>"},
{"nil *int", (*int)(nil), "0"},
{"nil *float64", (*float64)(nil), "0"},
{"nil *time.Time", (*time.Time)(nil), ""},
}

func TestToString(t *testing.T) {
Expand All @@ -153,8 +160,8 @@ var testCasesFloatToString = []numberConversionTest{
{"uint8", numberConversionInputData._uint8, "PANIC"},
{"uint", numberConversionInputData._uint, "PANIC"},
{"byte", numberConversionInputData._byte, "PANIC"},
{"float64", numberConversionInputData._float64, "100.12345678"},
{"float32", numberConversionInputData._float32, "100.1234"},
{"float64", numberConversionInputData._float64, "1234.12345678"},
{"float32", numberConversionInputData._float32, "1234.1234"},
{"*int64", &numberConversionInputData._int64, "PANIC"},
{"*int32", &numberConversionInputData._int32, "PANIC"},
{"*int16", &numberConversionInputData._int16, "PANIC"},
Expand All @@ -166,10 +173,10 @@ var testCasesFloatToString = []numberConversionTest{
{"*uint8", &numberConversionInputData._uint8, "PANIC"},
{"*uint", &numberConversionInputData._uint, "PANIC"},
{"*byte", &numberConversionInputData._byte, "PANIC"},
{"*float64 ", &numberConversionInputData._float64, "100.12345678"},
{"*float32", &numberConversionInputData._float32, "100.1234"},
{"*float64", &numberConversionInputData._float64, "1234.12345678"},
{"*float32", &numberConversionInputData._float32, "1234.1234"},
{"map", numberConversionInputData._map, "PANIC"},
{"floatAsString", numberConversionInputData._float_as_string, "100.12345678"},
{"floatAsString", numberConversionInputData._float_as_string, "1234567.12345678"},
}

func TestFloatToString(t *testing.T) {
Expand All @@ -179,34 +186,34 @@ func TestFloatToString(t *testing.T) {
}

var testCasesIntToString = []numberConversionTest{
{"int64", numberConversionInputData._int64, "100"},
{"int32", numberConversionInputData._int32, "100"},
{"int16", numberConversionInputData._int16, "100"},
{"int64", numberConversionInputData._int64, "1234567"},
{"int32", numberConversionInputData._int32, "1234567"},
{"int16", numberConversionInputData._int16, "1234567"},
{"int8", numberConversionInputData._int8, "100"},
{"int", numberConversionInputData._int, "100"},
{"uint64", numberConversionInputData._uint64, "100"},
{"uint32", numberConversionInputData._uint32, "100"},
{"uint16", numberConversionInputData._uint16, "100"},
{"int", numberConversionInputData._int, "1234567"},
{"uint64", numberConversionInputData._uint64, "1234567"},
{"uint32", numberConversionInputData._uint32, "1234567"},
{"uint16", numberConversionInputData._uint16, "12345"},
{"uint8", numberConversionInputData._uint8, "100"},
{"uint", numberConversionInputData._uint, "100"},
{"uint", numberConversionInputData._uint, "1234567"},
{"byte", numberConversionInputData._byte, "100"},
{"float64", numberConversionInputData._float64, "PANIC"},
{"float32", numberConversionInputData._float32, "PANIC"},
{"*int64", &numberConversionInputData._int64, "100"},
{"*int32", &numberConversionInputData._int32, "100"},
{"*int16", &numberConversionInputData._int16, "100"},
{"*int64", &numberConversionInputData._int64, "1234567"},
{"*int32", &numberConversionInputData._int32, "1234567"},
{"*int16", &numberConversionInputData._int16, "1234567"},
{"*int8", &numberConversionInputData._int8, "100"},
{"*int", &numberConversionInputData._int, "100"},
{"*uint64", &numberConversionInputData._uint64, "100"},
{"*uint32", &numberConversionInputData._uint32, "100"},
{"*uint16", &numberConversionInputData._uint16, "100"},
{"*int", &numberConversionInputData._int, "1234567"},
{"*uint64", &numberConversionInputData._uint64, "1234567"},
{"*uint32", &numberConversionInputData._uint32, "1234567"},
{"*uint16", &numberConversionInputData._uint16, "12345"},
{"*uint8", &numberConversionInputData._uint8, "100"},
{"*uint", &numberConversionInputData._uint, "100"},
{"*uint", &numberConversionInputData._uint, "1234567"},
{"*byte", &numberConversionInputData._byte, "100"},
{"*float64 ", &numberConversionInputData._float64, "PANIC"},
{"*float64", &numberConversionInputData._float64, "PANIC"},
{"*float32", &numberConversionInputData._float32, "PANIC"},
{"map", numberConversionInputData._map, "PANIC"},
{"intAsString", numberConversionInputData._int_as_string, "100"},
{"intAsString", numberConversionInputData._int_as_string, "1234567"},
{"floatAsString", numberConversionInputData._float_as_string, "PANIC"},
}

Expand Down Expand Up @@ -294,9 +301,9 @@ var testCasesToInt64 = []numberConversionTest{
{"int 32", numberConversionInputData._int32, int64(numberConversionInputData._int32)},
{"int 64", numberConversionInputData._int64, numberConversionInputData._int64},
{"int", numberConversionInputData._int, int64(numberConversionInputData._int)},
{"int as string", numberConversionInputData._int_as_string, int64(100)},
{"int as string", numberConversionInputData._int_as_string, int64(1234567)},
{"uint 8", numberConversionInputData._uint8, int64(numberConversionInputData._uint8)},
{"float", numberConversionInputData._float64, int64(100)},
{"float", numberConversionInputData._float64, int64(1234)},
{"invalid string", "FOO", "ERROR"},
}

Expand Down Expand Up @@ -325,7 +332,7 @@ var testCasesToFloat64 = []numberConversionTest{
{"float 32", numberConversionInputData._float32, float64(numberConversionInputData._float32)},
{"int 64", numberConversionInputData._int64, float64(numberConversionInputData._int64)},
{"float 64", numberConversionInputData._float64, numberConversionInputData._float64},
{"float as string", numberConversionInputData._float_as_string, float64(100.12345678)},
{"float as string", numberConversionInputData._float_as_string, float64(1234567.12345678)},
{"invalid string", "FOO", "ERROR"},
}

Expand Down Expand Up @@ -1873,3 +1880,57 @@ func TestMillisecondsTimeValue(t *testing.T) {
}
}
}

var testCasesToHumanisedString = []numberConversionTest{
// Basic number cases with humanisation
{"int64", numberConversionInputData._int64, "1,234,567"},
{"int32", numberConversionInputData._int32, "1,234,567"},
{"int16", numberConversionInputData._int16, "1,234,567"},
{"int8", numberConversionInputData._int8, "100"},
{"int", numberConversionInputData._int, "1,234,567"},
{"uint64", numberConversionInputData._uint64, "1,234,567"},
{"uint32", numberConversionInputData._uint32, "1,234,567"},
{"uint16", numberConversionInputData._uint16, "12,345"},
{"uint8", numberConversionInputData._uint8, "100"},
{"uint", numberConversionInputData._uint, "1,234,567"},
{"byte", numberConversionInputData._byte, "100"},
{"float64", numberConversionInputData._float64, "1,234.12345678"},
{"float32", numberConversionInputData._float32, "1,234.1234130859375"},

// Pointer cases with humanisation
{"*int64", &numberConversionInputData._int64, "1,234,567"},
{"*int32", &numberConversionInputData._int32, "1,234,567"},
{"*int16", &numberConversionInputData._int16, "1,234,567"},
{"*int8", &numberConversionInputData._int8, "100"},
{"*int", &numberConversionInputData._int, "1,234,567"},
{"*uint64", &numberConversionInputData._uint64, "1,234,567"},
{"*uint32", &numberConversionInputData._uint32, "1,234,567"},
{"*uint16", &numberConversionInputData._uint16, "12,345"},
{"*uint8", &numberConversionInputData._uint8, "100"},
{"*uint", &numberConversionInputData._uint, "1,234,567"},
{"*byte", &numberConversionInputData._byte, "100"},
{"*float64", &numberConversionInputData._float64, "1,234.12345678"},
{"*float32", &numberConversionInputData._float32, "1,234.1234130859375"},

// Nil pointer cases
{"nil *string", (*string)(nil), ""},
{"nil *bool", (*bool)(nil), "<nil>"},
{"nil *int", (*int)(nil), "0"},
{"nil *float64", (*float64)(nil), "0"},
{"nil *time.Time", (*time.Time)(nil), ""},

// Other types
{"string", "test", "test"},
{"bool", true, "true"},
{"time.Time", time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), "2024-01-01T00:00:00Z"},
{"[]byte", []byte("test"), "test"},
{"map", numberConversionInputData._map, "map[a:b]"},
{"struct", numberConversionInputData._struct, "{a:A}"},
{"enum", numberConversionInputData._enum, "a-val"},
}

func TestToHumanisedString(t *testing.T) {
for _, test := range testCasesToHumanisedString {
executeToStringTest(t, test, ToHumanisedString)
}
}
Loading