| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- package kit
- import (
- "fmt"
- "strings"
- "time"
- )
- const (
- DateLayout = "2006-01-02"
- DateTimeLayout = time.DateTime // 2006-01-02 15:04:05
- MonthLayout = "2006-01"
- )
- // ArgError 参数错误:Handler 返回给模型的可读说明。
- type ArgError struct{ Msg string }
- func (e *ArgError) Error() string { return e.Msg }
- func argErrorf(format string, a ...any) error { return &ArgError{Msg: fmt.Sprintf(format, a...)} }
- // Required 必填字符串参数(去掉首尾空白)。
- func Required(name, v string) (string, error) {
- v = strings.TrimSpace(v)
- if v == "" {
- return "", argErrorf("参数 %s 必填", name)
- }
- return v, nil
- }
- // ParseDate 解析 yyyy-MM-dd;v 为空且 allowEmpty 时返回 nil。
- func ParseDate(name, v string, allowEmpty bool) (*time.Time, error) {
- v = strings.TrimSpace(v)
- if v == "" {
- if allowEmpty {
- return nil, nil
- }
- return nil, argErrorf("参数 %s 必填,格式 yyyy-MM-dd", name)
- }
- t, err := time.Parse(DateLayout, v)
- if err != nil {
- return nil, argErrorf("参数 %s 格式错误,需要 yyyy-MM-dd:%s", name, v)
- }
- return &t, nil
- }
- // ParseDateTime 解析 yyyy-MM-dd HH:mm:ss;只给日期时按当天 00:00:00 处理。
- func ParseDateTime(name, v string) (time.Time, error) {
- v = strings.TrimSpace(v)
- if v == "" {
- return time.Time{}, argErrorf("参数 %s 必填,格式 yyyy-MM-dd HH:mm:ss", name)
- }
- if t, err := time.Parse(DateTimeLayout, v); err == nil {
- return t, nil
- }
- if t, err := time.Parse(DateLayout, v); err == nil {
- return t, nil
- }
- return time.Time{}, argErrorf("参数 %s 格式错误,需要 yyyy-MM-dd HH:mm:ss:%s", name, v)
- }
- // ParseRange 解析时间范围并检查 from < to、跨度不超过 max。
- func ParseRange(from, to string, max time.Duration) (time.Time, time.Time, error) {
- f, err := ParseDateTime("from", from)
- if err != nil {
- return f, f, err
- }
- t, err := ParseDateTime("to", to)
- if err != nil {
- return f, t, err
- }
- if !t.After(f) {
- return f, t, argErrorf("结束时间必须晚于开始时间")
- }
- if max > 0 && t.Sub(f) > max {
- return f, t, argErrorf("时间范围不能超过 %s,请缩短范围后分段查询", humanDuration(max))
- }
- return f, t, nil
- }
- func humanDuration(d time.Duration) string {
- if d%(24*time.Hour) == 0 {
- return fmt.Sprintf("%d 天", int(d/(24*time.Hour)))
- }
- return d.String()
- }
- // Limit 归一化条数:<=0 取默认值,超过上限取上限。
- func Limit(v, def, max int) int {
- if v <= 0 {
- return def
- }
- if v > max {
- return max
- }
- return v
- }
- // Page 归一化页码(从 1 开始)。
- func Page(v int) int {
- if v <= 0 {
- return 1
- }
- return v
- }
- // Enum 校验枚举值;v 为空返回默认值。
- func Enum(name, v, def string, allowed ...string) (string, error) {
- v = strings.TrimSpace(v)
- if v == "" {
- return def, nil
- }
- for _, a := range allowed {
- if strings.EqualFold(v, a) {
- return a, nil
- }
- }
- return "", argErrorf("参数 %s 取值错误:%s,可选值:%s", name, v, strings.Join(allowed, " / "))
- }
|