94 lines
2.0 KiB
Go
94 lines
2.0 KiB
Go
package money
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// CentsPerYuan 是人民币元与分的固定换算比例。
|
|
const CentsPerYuan int64 = 100
|
|
|
|
var ErrInvalidYuan = errors.New("金额格式不正确")
|
|
|
|
// ParseYuan 将用户输入的元字符串精确解析为分,不经过 float64。
|
|
// 支持 "12"、"12.3"、"12.34"、"-1.20";超过两位小数直接拒绝。
|
|
func ParseYuan(value string) (int64, error) {
|
|
trimmed := strings.TrimSpace(value)
|
|
if trimmed == "" {
|
|
return 0, ErrInvalidYuan
|
|
}
|
|
sign := int64(1)
|
|
if strings.HasPrefix(trimmed, "-") {
|
|
sign = -1
|
|
trimmed = strings.TrimPrefix(trimmed, "-")
|
|
} else if strings.HasPrefix(trimmed, "+") {
|
|
trimmed = strings.TrimPrefix(trimmed, "+")
|
|
}
|
|
if trimmed == "" {
|
|
return 0, ErrInvalidYuan
|
|
}
|
|
parts := strings.Split(trimmed, ".")
|
|
if len(parts) > 2 {
|
|
return 0, ErrInvalidYuan
|
|
}
|
|
wholeText := parts[0]
|
|
if wholeText == "" {
|
|
wholeText = "0"
|
|
}
|
|
whole, err := strconv.ParseInt(wholeText, 10, 64)
|
|
if err != nil || whole < 0 {
|
|
return 0, ErrInvalidYuan
|
|
}
|
|
fraction := int64(0)
|
|
if len(parts) == 2 {
|
|
fracText := parts[1]
|
|
if len(fracText) > 2 {
|
|
return 0, ErrInvalidYuan
|
|
}
|
|
fracText = fracText + strings.Repeat("0", 2-len(fracText))
|
|
if fracText == "" {
|
|
fracText = "00"
|
|
}
|
|
fraction, err = strconv.ParseInt(fracText, 10, 64)
|
|
if err != nil || fraction < 0 || fraction >= CentsPerYuan {
|
|
return 0, ErrInvalidYuan
|
|
}
|
|
}
|
|
if whole > (1<<62)/CentsPerYuan {
|
|
return 0, ErrInvalidYuan
|
|
}
|
|
return sign * (whole*CentsPerYuan + fraction), nil
|
|
}
|
|
|
|
// Format 将分精确格式化为两位小数,例如 1234 -> "12.34"。
|
|
// 全程使用整数运算,不经过 float64,也不做四舍五入。
|
|
func Format(cent int64) string {
|
|
sign := ""
|
|
value := cent
|
|
if value < 0 {
|
|
sign = "-"
|
|
value = -value
|
|
}
|
|
return fmt.Sprintf("%s%d.%02d", sign, value/CentsPerYuan, value%CentsPerYuan)
|
|
}
|
|
|
|
func FormatWithSymbol(cent int64) string {
|
|
return "¥" + Format(cent)
|
|
}
|
|
|
|
func MinCent(a, b int64) int64 {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
func MaxCent(a, b int64) int64 {
|
|
if a > b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|