辅助函数

This commit is contained in:
kercylan 2023-04-23 11:23:54 +08:00
parent 86e9e7400a
commit 165e99f08e
17 changed files with 618 additions and 1 deletions

40
utils/compress/gzip.go Normal file
View File

@ -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
}

14
utils/crypto/base64.go Normal file
View File

@ -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
}

15
utils/crypto/crc.go Normal file
View File

@ -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)
}

18
utils/crypto/md5.go Normal file
View File

@ -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))
}

18
utils/crypto/sha1.go Normal file
View File

@ -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))
}

17
utils/crypto/sha256.go Normal file
View File

@ -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[:])
}

View File

@ -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
}
}
}

View File

@ -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
}

18
utils/network/ip.go Normal file
View File

@ -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
}

23
utils/random/number.go Normal file
View File

@ -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()
}

75
utils/random/random.go Normal file
View File

@ -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)))
}

70
utils/random/string.go Normal file
View File

@ -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)
}

39
utils/slice/slice.go Normal file
View File

@ -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)
}
}

17
utils/str/range.go Normal file
View File

@ -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
}

2
utils/str/str.go Normal file
View File

@ -0,0 +1,2 @@
package str

118
utils/str/transform.go Normal file
View File

@ -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)
}

60
utils/times/format.go Normal file
View File

@ -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
}