Golang 的一些 helper 函数

package helper

import (
   "github.com/gogf/gf/os/gtime"
   "time"
)

const (
   DateFormat        = "2006-01-02"
   DateTimeFormat    = "2006-01-02 15:04:05"
   PHPDateForm       = "Y-m-d"
   PHPDateTimeFormat = "Y-m-d H:i:s"
)

//获取某天的开始时间
func GetDayStartFromTimestamp(timestamp int64) int64 {
   dateTimeStamp := gtime.NewFromTimeStamp(timestamp)
   //某天0点
   dateStr := dateTimeStamp.Format(PHPDateForm) + " 00:00:00"
   zeroTime, _ := gtime.StrToTime(dateStr)
   return zeroTime.Unix()
}

// 获取某天的开始时间
// dateStr 格式如2006-01-02 15:04:05
func GetDayStartFromStr(dateStr string) int64 {
   nowTime, err := gtime.StrToTime(dateStr)
   if err != nil {
      return 0
   }
   return GetDayStartFromTimestamp(nowTime.Unix())
}
func GetDayEndFromTimestamp(timestamp int64) int64 {
   dateTimeStamp := gtime.NewFromTimeStamp(timestamp)
   //某天23:59:59
   day := time.Second * 86400
   return dateTimeStamp.Add(day).Unix() - 1
}

// 获取某天的结束时间
// dateStr 格式如2006-01-02 15:04:05
func GetDayEndFromStr(dateStr string) int64 {
   nowTime, err := gtime.StrToTime(dateStr)
   if err != nil {
      return 0
   }
   return GetDayEndFromTimestamp(nowTime.Unix())
}
func TodayStartTime() int64 {
   timeStr := time.Now().Format("2006-01-02")
   t, _ := time.Parse("2006-01-02", timeStr)
   timeNumber := t.Unix()
   return timeNumber
}
func TodayEndTime() int64 {
   timeStr := time.Now().Add(time.Second * 86400).Format(DateFormat)
   t, _ := time.Parse(DateFormat, timeStr)
   timeNumber := t.Unix() - 1
   return timeNumber
}

//当前时间
func NowTime(args ...int) uint {
   var (
      nowTime uint
      timeAdd int
   )
   if len(args) > 0 {
      timeAdd = args[0]
      nowTime = uint(gtime.Now().Unix()) + uint(timeAdd)
   } else {
      nowTime = uint(gtime.Now().Unix())
   }
   return nowTime
}

// 同php in_array
func InArray(search interface{}, array interface{}, deep bool) bool {
   val := reflect.ValueOf(array)
   val = val.Convert(val.Type())

   typ := reflect.TypeOf(array).Kind()

   switch typ {
   case reflect.Map:
      s := val.MapRange()

      for s.Next() {
         s.Value().Convert(s.Value().Type())
         for i := 0; i < s.Value().Len(); i++ {
            if deep {
               if reflect.DeepEqual(search, s.Value().Index(i).Interface()) {
                  return true
               }
            } else {
               str := s.Value().Index(i).String()
               if strings.Contains(str, search.(string)) {
                  return true
               }
            }
         }
      }
   case reflect.Slice, reflect.Array:
      for i := 0; i < val.Len(); i++ {
         if reflect.DeepEqual(search, val.Index(i).Interface()) {
            return true
         }
      }
   }

   return false
}

// 获取配置信息
func Config(configFileDir string) *gcfg.Config {
   //获取当前工作目录
   if len(configFileDir) == 0 {
      curDir, _ := os.Getwd()
      parentDir := GetParentDirectory(curDir)
      configFileDir = parentDir + gfile.Separator + "config"
      if !gfile.IsDir(configFileDir) {
         msg := "配置文件目录不正确:" + configFileDir
         log.Fatalln(msg)
      }
   }

   g.Cfg().SetPath(configFileDir)
   return g.Cfg()
}

// 获取默认头像
func GetDefaultAvatar() string {
   avatar := g.Cfg().GetString("app.defaultAvatar")
   return avatar
}

// 截取字符
func Substr(s string, pos, length int) string {
   runes := []rune(s)
   l := pos + length
   if l > len(runes) {
      l = len(runes)
   }
   return string(runes[pos:l])
}

// 获取父级目录
func GetParentDirectory(dir string) string {
   return Substr(dir, 0, strings.LastIndex(dir, "/"))
}
func CheckRpcServer() error {
// err := genId.CheckGenIdHealth()
// if err != nil {
//    glog.Error(err)
//    return errors.New("请开启id grpc 服务")
// }
// err = password.CheckPwdHealth()
// if err != nil {
//    glog.Error(err)
//    return errors.New("请开启password grpc 服务")
// }
   return nil
}

// 日期格式 转 时间戳格式
func DatetimeToInt(datetime string) int64 {
   timeLayout := "2006-01-02 15:04:05"  //转化所需模板
   loc, _ := time.LoadLocation("Local") //获取时区
   tmp, _ := time.ParseInLocation(timeLayout, datetime, loc)
   return tmp.Unix() //转化为时间戳 类型是int64
}

// SliceDataValueToString 列表数据内容转字符串
func SliceDataValueToString(data interface{}, forceConvert ...string) (listData []map[string]interface{}) {
   listData = gconv.SliceMap(data)
   if len(listData) > 0 {
      for index, value := range listData {
         listData[index] = MapDataValueToString(value, forceConvert...)
      }
   }
   return
}

func GetMapKeys(m map[string]interface{}) []string {
   // 数组默认长度为map长度,后面append时,不需要重新申请内存和拷贝,效率较高
   j := 0
   keys := make([]string, len(m))
   for k := range m {
      keys[j] = k
      j++
   }
   return keys
}

// MapDataValueToString map数据内容转字符串
func MapDataValueToString(data interface{}, forceConvert ...string) map[string]interface{} {
   reData := gconv.Map(data)
   if len(reData) > 0 {
      for index, value := range reData {
         kind := reflect.TypeOf(value).Kind()
         mapKey := gconv.String(index)
         index = gconv.String(index)
         if kind == reflect.Slice || kind == reflect.Array {
            reData[index] = SliceDataValueToString(value, forceConvert...)
         } else if kind == reflect.Map {
            reData[index] = MapDataValueToString(value, forceConvert...)
         } else {
            if len(forceConvert) > 0 {
               for _, field := range forceConvert {
                  if mapKey == gconv.String(field) {
                     reData[mapKey] = gconv.String(value)
                  }
               }
            }
            intV := gconv.Int(value)
            if intV > math.MaxInt32 {
               reData[mapKey] = gconv.String(value)
            }
         }
      }
   }
   return reData
}
func TrimCdnUrl(url string) string {
   cdnUrl := g.Cfg().GetString("qiniu.cdnUrl")
   if strings.Contains(url, cdnUrl) {
      return gstr.TrimLeftStr(url, cdnUrl)
   }
   return url
}
func FixUploadUrl(key string) string {
   cdnUrl := g.Cfg().GetString("qiniu.cdnUrl")
   if strings.Contains(key, ":/") {
      return key
   }
   bg := strings.TrimPrefix(key, "/")
   cdnUrl = strings.TrimSuffix(cdnUrl, "/")
   url := fmt.Sprintf("%s/%s", cdnUrl, bg)
   return url
}

// 指定年月份的开始和结束时间
func GetYearMonthStartEndUnix(y int, m int) (int, int) {
   currentLocation := time.Now().Location()
   firstOfMonth := time.Date(y, time.Month(m), 1, 0, 0, 0, 0, currentLocation)
   start := gconv.Int(firstOfMonth.Unix())
   lastOfMonth := firstOfMonth.AddDate(0, 1, -1)
   end := gconv.Int(lastOfMonth.Unix() + 24*60*60 - 1)
   return start, end
}

func TrimHtml(src string) string {
   //将HTML标签全转换成小写
   re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
   src = re.ReplaceAllStringFunc(src, strings.ToLower)
   //去除STYLE
   re, _ = regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")
   src = re.ReplaceAllString(src, "")
   //去除SCRIPT
   re, _ = regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")
   src = re.ReplaceAllString(src, "")
   //去除所有尖括号内的HTML代码,并换成换行符
   re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
   src = re.ReplaceAllString(src, "\n")
   //去除连续的换行符
   re, _ = regexp.Compile("\\s{2,}")
   src = re.ReplaceAllString(src, "\n")
   return strings.TrimSpace(src)
}

//解析标注格式的list json
// str @example [{"sort":"1", "title":"", "image":"", "link":""}]
func ListJsonDecode(str string) ([]interface{}, error) {
   buf := []byte(str)
   var res []interface{}
   err := json.Unmarshal(buf, &res)
   if err != nil {
      return res, err
   }
   return res, nil
}

//解析标注格式的map list json
// str @example ["a":{"sort":"1", "title":"", "image":"", "link":""},"b":{"sort":"1", "title":"", "image":"",
//"link":""}]
func MapsJsonDecode(str string) (map[string]interface{}, error) {
   buf := []byte(str)
   var res map[string]interface{}
   err := json.Unmarshal(buf, &res)
   if err != nil {
      return res, err
   }
   return res, nil
}
func UrlEncode(url string) string {
   return netURL.QueryEscape(url)
}
func GetDataFileType(fileUrl string) int {
   dataFileType := g.Cfg().GetJsons("dataFileType")
   fileExt := gfile.ExtName(fileUrl)
   value := 0
   for _, val := range dataFileType {
      data := val.ToMap()
      if len(data) == 0 {
         continue
      }
      for _, v := range data {
         arrVal := gconv.SliceMap(v)
         innerData := arrVal[0]
         if len(innerData) == 0 {
            continue
         }
         extArr := gstr.SplitAndTrim(gconv.String(innerData["ext"]), "|", "|")
         for _, e := range extArr {
            if e == fileExt {
               value = gconv.Int(innerData["value"])
               break
            }
         }
         if value > 0 {
            break
         }
      }
      if value > 0 {
         break
      }
   }
   return value
}

// 手机号中间4位替换为*号
func FormatMobileStar(mobile string) string {
   if len(mobile) <= 10 {
      return mobile
   }
   return mobile[:3] + "****" + mobile[6:]
}


func IsEmpty(value interface{}) bool {
   if value == nil {
      return true
   }
   switch value := value.(type) {
   case int:
      return value == 0
   case int8:
      return value == 0
   case int16:
      return value == 0
   case int32:
      return value == 0
   case int64:
      return value == 0
   case uint:
      return value == 0
   case uint8:
      return value == 0
   case uint16:
      return value == 0
   case uint32:
      return value == 0
   case uint64:
      return value == 0
   case float32:
      return value == 0
   case float64:
      return value == 0
   case bool:
      return !value
   case string:
      return value == ""
   case []byte:
      return len(value) == 0
   default:
      // Finally using reflect.
      rv := reflect.ValueOf(value)
      switch rv.Kind() {
      case reflect.Chan,
         reflect.Map,
         reflect.Slice,
         reflect.Array:
         return rv.Len() == 0

      case reflect.Func,
         reflect.Ptr,
         reflect.Interface,
         reflect.UnsafePointer:
         if rv.IsNil() {
            return true
         }
      }
   }
   return false
}


//支持中文截取, 支持end 负数截取
func SubStr(source interface{}, start int, end int) string {
   str := source.(string)
   var r = []rune(str)
   length := len(r)
   subLen := end - start

   for {
      if start < 0 {
         break
      }
      if start == 0 && subLen == length {
         break
      }
      if end > length {
         subLen = length - start
      }
      if end < 0 {
         subLen = length - start + end
      }
      var substring bytes.Buffer
      if end > 0 {
         subLen = subLen + 1
      }
      for i := start; i < subLen; i++ {
         substring.WriteString(string(r[i]))
      }
      str = substring.String()

      break
   }

   return str
}

// 获取指定时间所在月的开始 结束时间
func GetMonthStartEnd(t time.Time) (time.Time, time.Time) {
   monthStartDay := t.AddDate(0, 0, -t.Day()+1)
   monthStartTime := time.Date(monthStartDay.Year(), monthStartDay.Month(), monthStartDay.Day(), 0, 0, 0, 0, t.Location())
   monthEndDay := monthStartTime.AddDate(0, 1, -1)
   monthEndTime := time.Date(monthEndDay.Year(), monthEndDay.Month(), monthEndDay.Day(), 23, 59, 59, 0, t.Location())
   return monthStartTime, monthEndTime
}


//处理金额 分 转换元
func FormatAmount(amount uint64) string {
   formatAmount := fmt.Sprintf("%.2f", gconv.Float64(amount)/100)
   //formatAmount, _ := strconv.ParseFloat(tmp, 64)

   return formatAmount
}

//处理金额 元 转分
func FormatAmountYuanToFen(amount string) uint64 {
   //会有精度问题 改进
   //formatAmount := gconv.Uint64(gconv.Float64(amount) * 100)

   d := decimal.New(1, 2)  //分转元乘以100
   d1 := decimal.New(1, 0) //乘完之后,保留2为小数,需要这么一个中间参数
   //df := decimal.NewFromFloat(price).Mul(d).DivRound(d1,2).String()
   //df := decimal.NewFromFloat(price).Mul(d).IntPart()

   //如下是满足,当乘以100后,仍然有小数位,取四舍五入法后,再取整数部分
   dff := decimal.NewFromFloat(gconv.Float64(amount)).Mul(d).DivRound(d1, 0).IntPart()

   return gconv.Uint64(dff)
}

// 获取指定时间月的开始时间
func GetFirstDateOfMonth(d time.Time) time.Time {
   d = d.AddDate(0, 0, -d.Day()+1)
   return GetDayZeroTime(d)
}

//获取传入的时间所在月份的结束时间
func GetLastDateOfMonth(d time.Time) time.Time {
   lastTime := GetFirstDateOfMonth(d).AddDate(0, 1, -1)
   return time.Date(lastTime.Year(), lastTime.Month(), lastTime.Day(), 23, 59, 59, 0, d.Location())
}

//获取某一天的0点时间
func GetDayZeroTime(d time.Time) time.Time {
   return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location())
}

//获取某一天的结束时间
func GetDayEndTime(d time.Time) time.Time {
   return time.Date(d.Year(), d.Month(), d.Day(), 23, 59, 59, 0, d.Location())
}

// 获取指定日期前一天的开始时间
func GetYesterdayZeroTime(d time.Time) time.Time {
   return time.Date(d.Year(), d.Month(), d.Day()-1, 0, 0, 0, 0, d.Location())
}

// 获取指定日期前一天的结束时间
func GetYesterdayEndTime(d time.Time) time.Time {
   return time.Date(d.Year(), d.Month(), d.Day()-1, 23, 59, 59, 0, d.Location())
}

// 获取指定日期当年的开始结束时间
func GetCurrentYearTime(d time.Time) (time.Time, time.Time) {
   currentLocation := time.Now().Location()
   start := time.Date(d.Year(), 1, 1, 0, 0, 0, 0, currentLocation)
   lastTime := start.AddDate(0, 12, -1)
   end := time.Date(lastTime.Year(), lastTime.Month(), lastTime.Day(), 23, 59, 59, 0, currentLocation)
   return start, end
}

// 获取指定时间的当周的开始结束时间
func GetWeekTime(d time.Time) (time.Time, time.Time) {
   offset := int(time.Monday - d.Weekday())
   if offset > 0 {
      offset = -6
   }
   weekStart := time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
   weekEndDay := weekStart.AddDate(0, 0, 6)
   weekEnd := time.Date(weekEndDay.Year(), weekEndDay.Month(), weekEndDay.Day(), 23, 59, 59, 0, time.Local)
   return weekStart, weekEnd
}

// 过滤编辑器传到后台的html
func EditorContentFilter(content string) (string, error) {
   allowTags := []string{"h1", "p", "span", "em", "strong", "blockquote", "a", "table", "tbody", "tr", "td", "figure", "img"}
   result, err := htmltags.Strip(content, allowTags, false)
   if err != nil {
      return "", err
   }
   return result.ToString(), nil
}

 

上一篇:算法很美——第三章:矩阵


下一篇:数据结构+算法--环形链表的创建和遍历 与 约瑟夫问题的解决