diff --git a/utils/compress/gzip.go b/utils/compress/gzip.go new file mode 100644 index 0000000..7991346 --- /dev/null +++ b/utils/compress/gzip.go @@ -0,0 +1,40 @@ +package compress + +import ( + "bytes" + "compress/gzip" + "io" +) + +// GZipCompress 对数据进行GZip压缩,返回bytes.Buffer和错误信息 +func GZipCompress(data []byte) (bytes.Buffer, error) { + var buf bytes.Buffer + gzipWriter := gzip.NewWriter(&buf) + _, err := gzipWriter.Write(data) + if err != nil { + return buf, err + } + if err := gzipWriter.Close(); err != nil { + return buf, err + } + return buf, nil +} + +// GZipUnCompress 对已进行GZip压缩的数据进行解压缩,返回字节数组及错误信息 +func GZipUnCompress(dataByte []byte) ([]byte, error) { + data := *bytes.NewBuffer(dataByte) + gzipReader, err := gzip.NewReader(&data) + if err != nil { + return nil, err + } + result, err := io.ReadAll(gzipReader) + if err != nil { + return nil, err + } + + if err := gzipReader.Close(); err != nil { + return nil, err + } + + return result, nil +} diff --git a/utils/crypto/base64.go b/utils/crypto/base64.go new file mode 100644 index 0000000..7205ab6 --- /dev/null +++ b/utils/crypto/base64.go @@ -0,0 +1,14 @@ +package kcrypto + +import "encoding/base64" + +// EncryptBase64 对数据进行Base64编码 +func EncryptBase64(data []byte) string { + return base64.StdEncoding.EncodeToString(data) +} + +// DecodedBase64 对数据进行Base64解码 +func DecodedBase64(data string) ([]byte, error) { + decoded, err := base64.StdEncoding.DecodeString(data) + return decoded, err +} diff --git a/utils/crypto/crc.go b/utils/crypto/crc.go new file mode 100644 index 0000000..d529d92 --- /dev/null +++ b/utils/crypto/crc.go @@ -0,0 +1,15 @@ +package kcrypto + +import ( + "hash/crc32" +) + +// EncryptCRC32 对字符串进行CRC加密并返回其结果。 +func EncryptCRC32(str string) uint32 { + return DecodedCRC32([]byte(str)) +} + +// DecodedCRC32 对字节数组进行CRC加密并返回其结果。 +func DecodedCRC32(data []byte) uint32 { + return crc32.ChecksumIEEE(data) +} diff --git a/utils/crypto/md5.go b/utils/crypto/md5.go new file mode 100644 index 0000000..f0a02c3 --- /dev/null +++ b/utils/crypto/md5.go @@ -0,0 +1,18 @@ +package kcrypto + +import ( + "crypto/md5" + "encoding/hex" +) + +// EncryptMD5 对字符串进行MD5加密并返回其结果。 +func EncryptMD5(str string) string { + return DecodedMD5([]byte(str)) +} + +// DecodedMD5 对字节数组进行MD5加密并返回其结果。 +func DecodedMD5(data []byte) string { + c := md5.New() + c.Write(data) + return hex.EncodeToString(c.Sum(nil)) +} diff --git a/utils/crypto/sha1.go b/utils/crypto/sha1.go new file mode 100644 index 0000000..b00d634 --- /dev/null +++ b/utils/crypto/sha1.go @@ -0,0 +1,18 @@ +package kcrypto + +import ( + "crypto/sha1" + "encoding/hex" +) + +// EncryptSHA1 对字符串进行SHA1加密并返回其结果。 +func EncryptSHA1(str string) string { + return DecodedSHA1([]byte(str)) +} + +// DecodedSHA1 对字节数组进行SHA1加密并返回其结果。 +func DecodedSHA1(data []byte) string { + c := sha1.New() + c.Write(data) + return hex.EncodeToString(c.Sum(nil)) +} diff --git a/utils/crypto/sha256.go b/utils/crypto/sha256.go new file mode 100644 index 0000000..567ab0d --- /dev/null +++ b/utils/crypto/sha256.go @@ -0,0 +1,17 @@ +package kcrypto + +import ( + "crypto/sha256" + "encoding/hex" +) + +// EncryptSHA256 对字符串进行SHA256加密并返回其结果。 +func EncryptSHA256(str string) string { + return DecodedSHA256([]byte(str)) +} + +// DecodedSHA256 对字节数组进行SHA256加密并返回其结果。 +func DecodedSHA256(data []byte) string { + bytes := sha256.Sum256(data) + return hex.EncodeToString(bytes[:]) +} diff --git a/utils/file/file.go b/utils/file/file.go index e257bd5..59781de 100644 --- a/utils/file/file.go +++ b/utils/file/file.go @@ -1,6 +1,10 @@ package file -import "os" +import ( + "bufio" + "io" + "os" +) // PathExist 路径是否存在 func PathExist(path string) (bool, error) { @@ -22,3 +26,54 @@ func IsDir(path string) (bool, error) { } return false, err } + +// WriterFile 向特定文件写入内容 +func WriterFile(filePath string, content []byte) error { + f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) + if err != nil { + return err + } else { + // offset + //os.Truncate(filename, 0) //clear + n, _ := f.Seek(0, io.SeekEnd) + _, err = f.WriteAt(content, n) + _ = f.Close() + } + return nil +} + +// ReadOnce 单次读取文件 +// - 一次性对整个文件进行读取,小文件读取可以很方便的一次性将文件内容读取出来,而大文件读取会造成性能影响。 +func ReadOnce(filePath string) ([]byte, error) { + if file, err := os.Open(filePath); err != nil { + return nil, err + } else { + _ = file.Close() + return io.ReadAll(file) + } +} + +// ReadBlockHook 分块读取文件 +// - 将filePath路径对应的文件数据并将读到的每一部分传入hook函数中,当过程中如果产生错误则会返回error。 +// - 分块读取可以在读取速度和内存消耗之间有一个很好的平衡。 +func ReadBlockHook(filePath string, bufferSize int, hook func(data []byte)) error { + file, err := os.Open(filePath) + if err != nil { + return err + } + defer func() { + _ = file.Close() + }() + buffer := make([]byte, bufferSize) + bufferReader := bufio.NewReader(file) + for { + successReadSize, err := bufferReader.Read(buffer) + hook(buffer[:successReadSize]) + if err != nil { + if err == io.EOF { + return nil + } + return err + } + } +} diff --git a/utils/hash/convert.go b/utils/hash/convert.go index cd79134..d4add77 100644 --- a/utils/hash/convert.go +++ b/utils/hash/convert.go @@ -26,3 +26,21 @@ func Reversal[K comparable, V comparable](m map[K]V) map[V]K { } return nm } + +// ToMap 将切片转换为 map +func ToMap[V any](slice []V) map[int]V { + var m = make(map[int]V) + for i, v := range slice { + m[i] = v + } + return m +} + +// ToSortMap 将切片转换为 SortMap +func ToSortMap[V any](slice []V) SortMap[int, V] { + var m SortMap[int, V] + for i, v := range slice { + m.Set(i, v) + } + return m +} diff --git a/utils/network/ip.go b/utils/network/ip.go new file mode 100644 index 0000000..2f877bc --- /dev/null +++ b/utils/network/ip.go @@ -0,0 +1,18 @@ +package network + +import ( + "net" +) + +// IP 返回本机出站地址 +func IP() (ip net.IP, err error) { + var conn net.Conn + conn, err = net.Dial("udp", "8.8.8.8:80") + if err != nil { + return + } + _ = conn.Close() + localAddr := conn.LocalAddr().(*net.UDPAddr) + ip = localAddr.IP + return +} diff --git a/utils/random/number.go b/utils/random/number.go new file mode 100644 index 0000000..11cf867 --- /dev/null +++ b/utils/random/number.go @@ -0,0 +1,23 @@ +package random + +import "math/rand" + +// Int64 返回一个介于min和max之间的int64类型的随机数。 +func Int64(min int64, max int64) int64 { + return min + rand.Int63n(max-min) +} + +// Int 返回一个介于min和max之间的的int类型的随机数。 +func Int(min int, max int) int { + return int(Int64(int64(min), int64(max))) +} + +// Float64 返回一个0~1的浮点数 +func Float64() float64 { + return rand.Float64() +} + +// Float32 返回一个0~1的浮点数 +func Float32() float32 { + return rand.Float32() +} diff --git a/utils/random/random.go b/utils/random/random.go new file mode 100644 index 0000000..b1204b8 --- /dev/null +++ b/utils/random/random.go @@ -0,0 +1,75 @@ +package random + +import ( + "math/rand" + "time" +) + +var ( + engName, lastName, firstName []string + lastNameLen, firstNameLen, englishNameLen int +) + +func init() { + engName = []string{ + "Smith", "Johnson", "Williams", "Jones", "Brown", "Davis", "Miller", "Wilson", "Moore", "Taylor", + "Anderson", "Thomas", "Jackson", "White", "Harris", "Martin", "Thompson", "Garcia", "Martinez", + "Robinson", "Clark", "Rodriguez", "Lewis", "Lee", "Walker", "Hall", "Allen", "Young", "Hernandez", + "King", "Wright", "Lopez", "Hill", "Scott", "Green", "Adams", "Baker", "Gonzalez", "Nelson", "Carter", + "Mitchell", "Perez", "Roberts", "Turner", "Phillips", "Campbell", "Parker", "Evans", "Edwards", + "Collins", "Stewart", "Sanchez", "Morris", "Rogers", "Reed", "Cook", "Morgan", "Bell", "Murphy", + "Bailey", "Rivera", "Cooper", "Richardson", "Cox", "Howard", "Ward", "Torres", "Peterson", "Gray", + "Ramirez", "James", "Watson", "Brooks", "Kelly", "Sanders", "Price", "Bennett", "Wood", "Barnes", + "Ross", "Henderson", "Coleman", "Jenkins", "Perry", "Powell", "Long", "Patterson", "Hughes", "Flores", + "Washington", "Butler", "Simmons", "Foster", "Gonzales", "Bryant", "Alexander", "Russell", "Griffin", "Diaz", "Hayes"} + lastName = []string{ + "赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", + "沈", "韩", "杨", "朱", "秦", "尤", "许", "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", + "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", + "郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "任", "袁", "柳", "鲍", "史", "唐", "费", "薛", + "雷", "贺", "倪", "汤", "滕", "殷", "罗", "毕", "郝", "安", "常", "傅", "卞", "齐", "元", "顾", "孟", + "平", "黄", "穆", "萧", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "狄", "米", "伏", "成", "戴", "谈", + "宋", "茅", "庞", "熊", "纪", "舒", "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "季", "贾", + "路", "娄", "江", "童", "颜", "郭", "梅", "盛", "林", "钟", "徐", "邱", "骆", "高", "夏", "蔡", "田", + "樊", "胡", "凌", "霍", "虞", "万", "支", "柯", "管", "卢", "莫", "柯", "房", "裘", "缪", "解", "应", + "宗", "丁", "宣", "邓", "单", "杭", "洪", "包", "诸", "左", "石", "崔", "吉", "龚", "程", "嵇", "邢", + "裴", "陆", "荣", "翁", "荀", "于", "惠", "甄", "曲", "封", "储", "仲", "伊", "宁", "仇", "甘", "武", + "符", "刘", "景", "詹", "龙", "叶", "幸", "司", "黎", "溥", "印", "怀", "蒲", "邰", "从", "索", "赖", + "卓", "屠", "池", "乔", "胥", "闻", "莘", "党", "翟", "谭", "贡", "劳", "逄", "姬", "申", "扶", "堵", + "冉", "宰", "雍", "桑", "寿", "通", "燕", "浦", "尚", "农", "温", "别", "庄", "晏", "柴", "瞿", "阎", + "连", "习", "容", "向", "古", "易", "廖", "庾", "终", "步", "都", "耿", "满", "弘", "匡", "国", "文", + "寇", "广", "禄", "阙", "东", "欧", "利", "师", "巩", "聂", "关", "荆", "司马", "上官", "欧阳", "夏侯", + "诸葛", "闻人", "东方", "赫连", "皇甫", "尉迟", "公羊", "澹台", "公冶", "宗政", "濮阳", "淳于", "单于", + "太叔", "申屠", "公孙", "仲孙", "轩辕", "令狐", "徐离", "宇文", "长孙", "慕容", "司徒", "司空"} + firstName = []string{ + "伟", "刚", "勇", "毅", "俊", "峰", "强", "军", "平", "保", "东", "文", "辉", "力", "明", "永", "健", "世", "广", "志", "义", + "兴", "良", "海", "山", "仁", "波", "宁", "贵", "福", "生", "龙", "元", "全", "国", "胜", "学", "祥", "才", "发", "武", "新", + "利", "清", "飞", "彬", "富", "顺", "信", "子", "杰", "涛", "昌", "成", "康", "星", "光", "天", "达", "安", "岩", "中", "茂", + "进", "林", "有", "坚", "和", "彪", "博", "诚", "先", "敬", "震", "振", "壮", "会", "思", "群", "豪", "心", "邦", "承", "乐", + "绍", "功", "松", "善", "厚", "庆", "磊", "民", "友", "裕", "河", "哲", "江", "超", "浩", "亮", "政", "谦", "亨", "奇", "固", + "之", "轮", "翰", "朗", "伯", "宏", "言", "若", "鸣", "朋", "斌", "梁", "栋", "维", "启", "克", "伦", "翔", "旭", "鹏", "泽", + "晨", "辰", "士", "以", "建", "家", "致", "树", "炎", "德", "行", "时", "泰", "盛", "雄", "琛", "钧", "冠", "策", "腾", "楠", + "榕", "风", "航", "弘", "秀", "娟", "英", "华", "慧", "巧", "美", "娜", "静", "淑", "惠", "珠", "翠", "雅", "芝", "玉", "萍", + "红", "娥", "玲", "芬", "芳", "燕", "彩", "春", "菊", "兰", "凤", "洁", "梅", "琳", "素", "云", "莲", "真", "环", "雪", "荣", + "爱", "妹", "霞", "香", "月", "莺", "媛", "艳", "瑞", "凡", "佳", "嘉", "琼", "勤", "珍", "贞", "莉", "桂", "娣", "叶", "璧", + "璐", "娅", "琦", "晶", "妍", "茜", "秋", "珊", "莎", "锦", "黛", "青", "倩", "婷", "姣", "婉", "娴", "瑾", "颖", "露", "瑶", + "怡", "婵", "雁", "蓓", "纨", "仪", "荷", "丹", "蓉", "眉", "君", "琴", "蕊", "薇", "菁", "梦", "岚", "苑", "婕", "馨", "瑗", + "琰", "韵", "融", "园", "艺", "咏", "卿", "聪", "澜", "纯", "毓", "悦", "昭", "冰", "爽", "琬", "茗", "羽", "希", "欣", "飘", + "育", "滢", "馥", "筠", "柔", "竹", "霭", "凝", "晓", "欢", "霄", "枫", "芸", "菲", "寒", "伊", "亚", "宜", "可", "姬", "舒", + "影", "荔", "枝", "丽", "阳", "妮", "宝", "贝", "初", "程", "梵", "罡", "恒", "鸿", "桦", "骅", "剑", "娇", "纪", "宽", "苛", + "灵", "玛", "媚", "琪", "晴", "容", "睿", "烁", "堂", "唯", "威", "韦", "雯", "苇", "萱", "阅", "彦", "宇", "雨", "洋", "忠", + "宗", "曼", "紫", "逸", "贤", "蝶", "菡", "绿", "蓝", "儿", "翠", "烟", "小", "轩"} + lastNameLen = len(lastName) + firstNameLen = len(firstName) + englishNameLen = len(engName) + + rand.NewSource(time.Now().UnixNano() + int64(rand.Intn(999))) +} + +func RefreshSeed(seed ...int64) { + if len(seed) > 0 { + rand.NewSource(seed[0]) + return + } + rand.NewSource(time.Now().UnixNano() + int64(rand.Intn(999))) +} diff --git a/utils/random/string.go b/utils/random/string.go new file mode 100644 index 0000000..c3005b1 --- /dev/null +++ b/utils/random/string.go @@ -0,0 +1,70 @@ +package random + +import ( + "fmt" + "math/rand" + "strconv" +) + +// ChineseName 返回一个随机组成的中文姓名。 +func ChineseName() string { + var first string // 名 + // 随机产生2位或者3位的名 + for i := 0; i <= rand.Intn(1); i++ { + first = fmt.Sprint(firstName[rand.Intn(firstNameLen-1)]) + } + //返回姓名 + return fmt.Sprintf("%s%s", fmt.Sprint(lastName[rand.Intn(lastNameLen-1)]), first) +} + +// EnglishName 返回一个随机组成的英文姓名。 +func EnglishName() string { + var englishName string + for i := 0; i <= rand.Intn(1); i++ { + englishName = fmt.Sprint(engName[rand.Intn(englishNameLen-1)]) + } + first := engName[rand.Intn(englishNameLen-1)] + last := englishName + if first == last { + return first + } else { + return fmt.Sprintf("%s %s", fmt.Sprint(engName[rand.Intn(englishNameLen-1)]), englishName) + } +} + +// Name 返回一个随机组成的中文或英文姓名 +// - 以1/2的概率决定生产的是中文还是英文姓名。 +func Name() string { + if Int64(0, 1000) > 500 { + return EnglishName() + } else { + return ChineseName() + } +} + +// NumberString 返回一个介于min和max之间的string类型的随机数。 +func NumberString(min int, max int) string { + return strconv.Itoa(int(Int64(int64(min), int64(max)))) +} + +// NumberStringRepair 返回一个介于min和max之间的string类型的随机数 +// - 通过Int64生成一个随机数,当结果的字符串长度小于max的字符串长度的情况下,使用0在开头补齐。 +func NumberStringRepair(min int, max int) string { + result := strconv.Itoa(int(Int64(int64(min), int64(max)))) + for i := len(result); i < len(strconv.Itoa(max)); i++ { + result = "0" + result + } + return result +} + +// HostName 返回一个随机产生的hostname。 +func HostName() string { + str := "0123456789abcdefghijklmnopqrstuvwxyz" + bytes := []byte(str) + var hostname []byte + r := rand.New(rand.NewSource(Int64(0, 999999))) + for i := 0; i < 12; i++ { + hostname = append(hostname, bytes[r.Intn(len(bytes))]) + } + return string(hostname) +} diff --git a/utils/slice/slice.go b/utils/slice/slice.go new file mode 100644 index 0000000..480b55c --- /dev/null +++ b/utils/slice/slice.go @@ -0,0 +1,39 @@ +package slice + +// Del 删除特定索引的元素 +func Del[V any](slice *[]V, index int) { + s := *slice + if index < 0 { + index = 0 + } else if index >= len(*slice) { + index = len(*slice) - 1 + } + *slice = append(s[:index], s[index+1:]...) +} + +// Insert 在特定索引插入元素 +func Insert[V any](slice *[]V, index int, value V) { + s := *slice + if index <= 0 { + *slice = append([]V{value}, s...) + } else if index >= len(s) { + *slice = append(s, value) + } else { + *slice = append(s[:index], append([]V{value}, s[index:]...)...) + } +} + +// Move 移动特定索引 +func Move[V any](slice *[]V, index, to int) { + s := *slice + v := s[index] + if index == to { + return + } else if to < index { + Del[V](slice, index) + Insert(slice, to, v) + } else { + Insert(slice, to, v) + Del[V](slice, index) + } +} diff --git a/utils/str/range.go b/utils/str/range.go new file mode 100644 index 0000000..a5d4697 --- /dev/null +++ b/utils/str/range.go @@ -0,0 +1,17 @@ +package str + +import "strings" + +// RangeLine 对传入的eachString进行按行切片后再进行遍历 +// - 该函数会预先对“\r\n”进行处理替换为“\n”。 +// - 在遍历到每一行的时候会将结果index和line作为入参传入eachFunc中进行调用。 +// - index表示了当前行的行号(由0开始),line表示了当前行的内容。 +func RangeLine(eachString string, eachFunc func(index int, line string) error) error { + formatStr := strings.ReplaceAll(eachString, "\r\n", "\n") + for index, line := range strings.Split(formatStr, "\n") { + if err := eachFunc(index, line); err != nil { + return err + } + } + return nil +} diff --git a/utils/str/str.go b/utils/str/str.go new file mode 100644 index 0000000..df8f7e7 --- /dev/null +++ b/utils/str/str.go @@ -0,0 +1,2 @@ +package str + diff --git a/utils/str/transform.go b/utils/str/transform.go new file mode 100644 index 0000000..39824e9 --- /dev/null +++ b/utils/str/transform.go @@ -0,0 +1,118 @@ +package str + +import ( + "regexp" + "strconv" + "strings" +) + +// HideSensitivity 返回防敏感化后的字符串 +// - 隐藏身份证、邮箱、手机号等敏感信息用*号替代 +func HideSensitivity(str string) (result string) { + if str == "" { + return "***" + } + if strings.Contains(str, "@") { + res := strings.Split(str, "@") + if len(res[0]) < 3 { + resString := "***" + result = resString + "@" + res[1] + } else { + resRs := []rune(str) + res2 := string(resRs[0:3]) + resString := res2 + "***" + result = resString + "@" + res[1] + } + return result + } else { + reg := `^1[0-9]\d{9}$` + rgx := regexp.MustCompile(reg) + mobileMatch := rgx.MatchString(str) + if mobileMatch { + rs := []rune(str) + result = string(rs[0:5]) + "****" + string(rs[7:11]) + + } else { + nameRune := []rune(str) + lens := len(nameRune) + + if lens <= 1 { + result = "***" + } else if lens == 2 { + result = string(nameRune[:1]) + "*" + } else if lens == 3 { + result = string(nameRune[:1]) + "*" + string(nameRune[2:3]) + } else if lens == 4 { + result = string(nameRune[:1]) + "**" + string(nameRune[lens-1:lens]) + } else if lens > 4 { + result = string(nameRune[:2]) + "***" + string(nameRune[lens-2:lens]) + } + } + return + } +} + +// ThousandsSeparator 返回将str进行千位分隔符处理后的字符串。 +func ThousandsSeparator(str string) string { + length := len(str) + if length < 4 { + return str + } + arr := strings.Split(str, ".") //用小数点符号分割字符串,为数组接收 + length1 := len(arr[0]) + if length1 < 4 { + return str + } + count := (length1 - 1) / 3 + for i := 0; i < count; i++ { + arr[0] = arr[0][:length1-(i+1)*3] + "," + arr[0][length1-(i+1)*3:] + } + return strings.Join(arr, ".") //将一系列字符串连接为一个字符串,之间用sep来分隔。 +} + +// KV 返回str经过转换后形成的key、value +// - 这里tag表示使用什么字符串来区分key和value的分隔符。 +// - 默认情况即不传入tag的情况下分隔符为“=”。 +func KV(str string, tag ...string) (string, string) { + tagChar := "=" + if len(tag) > 0 { + tagChar = tag[0] + } + kv := strings.SplitN(str, tagChar, 2) + if len(kv) < 2 { + return "", "" + } + return kv[0], kv[1] +} + +// FormatSpeedyInt 返回numberStr经过格式化后去除空格和“,”分隔符的结果 +// - 当字符串为“123,456,789”的时候,返回结果为“123456789”。 +// - 当字符串为“123 456 789”的时候,返回结果为“123456789”。 +// - 当字符串为“1 23, 45 6, 789”的时候,返回结果为“123456789”。 +func FormatSpeedyInt(numberStr string) (int, error) { + return strconv.Atoi(strings.ReplaceAll(strings.ReplaceAll(numberStr, " ", ""), ",", "")) +} + +// FormatSpeedyInt64 返回numberStr经过格式化后去除空格和“,”分隔符的结果 +// - 当字符串为“123,456,789”的时候,返回结果为“123456789”。 +// - 当字符串为“123 456 789”的时候,返回结果为“123456789”。 +// - 当字符串为“1 23, 45 6, 789”的时候,返回结果为“123456789”。 +func FormatSpeedyInt64(numberStr string) (int64, error) { + return strconv.ParseInt(strings.ReplaceAll(strings.ReplaceAll(numberStr, " ", ""), ",", ""), 10, 64) +} + +// FormatSpeedyFloat32 返回numberStr经过格式化后去除空格和“,”分隔符的结果 +// - 当字符串为“123,456,789.123”的时候,返回结果为“123456789.123”。 +// - 当字符串为“123 456 789.123”的时候,返回结果为“123456789.123”。 +// - 当字符串为“1 23, 45 6, 789.123”的时候,返回结果为“123456789.123”。 +func FormatSpeedyFloat32(numberStr string) (float64, error) { + return strconv.ParseFloat(strings.ReplaceAll(strings.ReplaceAll(numberStr, " ", ""), ",", ""), 32) +} + +// FormatSpeedyFloat64 返回numberStr经过格式化后去除空格和“,”分隔符的结果 +// - 当字符串为“123,456,789.123”的时候,返回结果为“123456789.123”。 +// - 当字符串为“123 456 789.123”的时候,返回结果为“123456789.123”。 +// - 当字符串为“1 23, 45 6, 789.123”的时候,返回结果为“123456789.123”。 +func FormatSpeedyFloat64(numberStr string) (float64, error) { + return strconv.ParseFloat(strings.ReplaceAll(strings.ReplaceAll(numberStr, " ", ""), ",", ""), 64) +} diff --git a/utils/times/format.go b/utils/times/format.go new file mode 100644 index 0000000..ed3c29c --- /dev/null +++ b/utils/times/format.go @@ -0,0 +1,60 @@ +package times + +import ( + "fmt" + "math" + "strconv" + "time" +) + +const ( + IntervalYear = iota + IntervalDay + IntervalHour + IntervalMinute + IntervalSecond +) + +var ( + intervalFormat = map[int]string{ + IntervalYear: "年前", + IntervalDay: "天前", + IntervalHour: "小时前", + IntervalMinute: "分钟前", + IntervalSecond: "秒钟前", + } +) + +// IntervalFormatSet 针对 IntervalFormat 函数设置格式化内容 +func IntervalFormatSet(intervalType int, str string) { + if intervalType < IntervalYear || intervalType > IntervalSecond { + return + } + intervalFormat[intervalType] = str +} + +// IntervalFormat 返回指定时间戳之间的间隔 +// - 使用传入的时间进行计算换算,将结果体现为几年前、几天前、几小时前、几分钟前、几秒前。 +func IntervalFormat(time1, time2 time.Time) string { + var byTime = []int64{365 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60, 1} + cur := time1.Unix() + ct := cur - time2.Unix() + if ct <= 0 { + return "刚刚" + } + var res string + for i := 0; i < len(byTime); i++ { + if ct < byTime[i] { + continue + } + var temp = math.Floor(float64(ct / byTime[i])) + ct = ct % byTime[i] + if temp > 0 { + var tempStr string + tempStr = strconv.FormatFloat(temp, 'f', -1, 64) + res = fmt.Sprint(tempStr, intervalFormat[i]) + } + break + } + return res +}