Skip to content

Commit

Permalink
fix: fix DecimalBytes and BinaryBytes issue #232
Browse files Browse the repository at this point in the history
  • Loading branch information
duke-git committed Aug 19, 2024
1 parent c0b200f commit bc26027
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 16 deletions.
47 changes: 31 additions & 16 deletions formatter/byte.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"strconv"
"strings"
"unicode"

"github.com/duke-git/lancet/v2/mathutil"
"github.com/duke-git/lancet/v2/strutil"
)

//
Expand Down Expand Up @@ -91,32 +94,21 @@ func DecimalBytes(size float64, precision ...int) string {

size, unit := calculateByteSize(size, 1000.0, decimalByteUnits)

format := fmt.Sprintf("%%.%df", pointPosition)
bytes := fmt.Sprintf(format, size)

for i := len(bytes); i > 0; i-- {
s := bytes[i-1]
if s != '0' && s != '.' {
break
}

bytes = bytes[:i-1]
}

return bytes + unit
return roundToToString(size, pointPosition) + unit
}

// BinaryBytes returns a human-readable byte size under binary standard (base 1024)
// The precision parameter specifies the number of digits after the decimal point, which defaults to 4.
// Play: https://go.dev/play/p/G9oHHMCAZxP
func BinaryBytes(size float64, precision ...int) string {
p := 5
pointPosition := 4
if len(precision) > 0 {
p = precision[0] + 1
pointPosition = precision[0]
}

size, unit := calculateByteSize(size, 1024.0, binaryByteUnits)

return fmt.Sprintf("%.*g%s", p, size, unit)
return roundToToString(size, pointPosition) + unit
}

func calculateByteSize(size float64, base float64, byteUnits []string) (float64, string) {
Expand All @@ -129,6 +121,29 @@ func calculateByteSize(size float64, base float64, byteUnits []string) (float64,
return size, byteUnits[i]
}

func roundToToString(x float64, max ...int) string {
pointPosition := 4
if len(max) > 0 {
pointPosition = max[0]
}
result := mathutil.RoundToString(x, pointPosition)

// 删除小数位结尾的0
decimal := strings.TrimRight(strutil.After(result, "."), "0")
if decimal == "" || pointPosition == 0 {
// 没有小数位直接返回整数
return strutil.Before(result, ".")
}

// 小数位大于想要设置的位数,按需要截断
if len(decimal) > pointPosition {
return strutil.Before(result, ".") + "." + decimal[:pointPosition]
}

// 小数位小于等于想要的位数,直接拼接返回
return strutil.Before(result, ".") + "." + decimal
}

// ParseDecimalBytes return the human readable bytes size string into the amount it represents(base 1000).
// ParseDecimalBytes("42 MB") -> 42000000, nil
// Play: https://go.dev/play/p/Am98ybWjvjj
Expand Down
7 changes: 7 additions & 0 deletions formatter/byte_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ func TestDecimalBytes(t *testing.T) {
assert.Equal("401MB", DecimalBytes(401000000))
assert.Equal("401MB", DecimalBytes(401000000, 0))
assert.Equal("4MB", DecimalBytes(4010000, 0))

assert.Equal("4MB", DecimalBytes(4000000, 0))
assert.Equal("4MB", DecimalBytes(4000000, 1))
}

func TestBinaryBytes(t *testing.T) {
Expand All @@ -36,6 +39,10 @@ func TestBinaryBytes(t *testing.T) {
assert.Equal("1MiB", BinaryBytes(1024*1024))
assert.Equal("1.1774MiB", BinaryBytes(1234567))
assert.Equal("1.18MiB", BinaryBytes(1234567, 2))

assert.Equal("10KiB", BinaryBytes(10240, 0))
assert.Equal("10KiB", BinaryBytes(10240, 1))
assert.Equal("10KiB", BinaryBytes(10240, 2))
}

func TestParseDecimalBytes(t *testing.T) {
Expand Down

0 comments on commit bc26027

Please sign in to comment.