123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709 |
- package common
- import (
- date4 "app.yhyue.com/moapp/jybase/date"
- "app.yhyue.com/moapp/jybase/encrypt"
- "crypto/md5"
- cryptoRand "crypto/rand"
- "encoding/hex"
- "encoding/json"
- "encoding/xml"
- "fmt"
- "github.com/dchest/captcha"
- "io"
- "log"
- "math"
- "math/big"
- mathRand "math/rand"
- "net/url"
- "reflect"
- "regexp"
- "runtime"
- "sort"
- "strconv"
- "strings"
- "time"
- )
- const (
- tmp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678900"
- )
- //短地址加密
- func EncodeArticleId(keys ...string) string {
- kstr := strings.Join(keys, ",")
- return encrypt.SE.EncodeString(kstr)
- }
- //短地址解密
- func DecodeArticleId(id string) []string {
- return strings.Split(encrypt.SE.DecodeString(id), ",")
- }
- //短地址加密,二次加密带校验和
- func EncodeArticleId2ByCheck(keys ...string) string {
- kstr := strings.Join(keys, ",")
- kstr = encrypt.SE.EncodeStringByCheck(kstr)
- return url.QueryEscape("ABC" + encrypt.SE2.EncodeStringByCheck(kstr))
- }
- //短地址解密,二次解密带校验和
- func DecodeArticleId2ByCheck(id string) []string {
- if !strings.Contains(id, "+") { //新加密算法解密
- id, _ = url.QueryUnescape(id)
- }
- if id[:3] == "ABC" { //前三位为ABC是新加密数据
- kstr := encrypt.SE2.DecodeStringByCheck(id[3:])
- return strings.Split(encrypt.SE.DecodeStringByCheck(kstr), ",")
- } else { //历史数据
- rep := DecodeArticleId(id)
- oldpushid := "58f87a9561a0721f157bc74d" //剑鱼1.9发版前最后一次推送信息id
- if rep[0] > oldpushid {
- return []string{""}
- } else {
- return rep
- }
- }
- }
- func Uuid(length int) string {
- ret := []string{}
- r := mathRand.New(mathRand.NewSource(time.Now().UnixNano()))
- for i := 0; i < length; i++ {
- index := r.Intn(62)
- ret = append(ret, tmp[index:index+1])
- }
- return strings.Join(ret, "")
- }
- //计算字符串和值
- func Sumstring(code string) (sum int) {
- tmp := []rune(code)
- for _, v := range tmp {
- sum = sum + int(v)
- }
- return
- }
- //获取随机数
- func GetRandom(n int) string {
- var idChars = []byte("0123456789")
- b := captcha.RandomDigits(n)
- for i, c := range b {
- b[i] = idChars[c]
- }
- return string(b)
- }
- //获取复杂的随机数
- func GetLetterRandom(length int, flag ...bool) string {
- var idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
- var mod byte = 52
- if len(flag) > 0 && flag[0] {
- idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
- mod = 26
- }
- b := make([]byte, length)
- maxrb := byte(256 - (256 % int(mod)))
- i := 0
- EXIT:
- for {
- r := make([]byte, length+(length/4))
- if _, err := io.ReadFull(cryptoRand.Reader, r); err != nil {
- panic("captcha: error reading random source: " + err.Error())
- }
- for _, c := range r {
- if c > maxrb {
- continue
- }
- b[i] = c % mod
- i++
- if i == length {
- break EXIT
- }
- }
- }
- for i, c := range b {
- b[i] = idChars[c]
- }
- return string(b)
- }
- /*获取复杂的随机数,数字和字母的组合
- * c > 2 数字的个数和字母的个数随机分配
- * n 数字的个数
- * l 字母的个数
- */
- func GetComplexRandom(c, n, l int) string {
- if c < 2 && (n < 1 || l < 1) {
- return "--"
- }
- r := mathRand.New(mathRand.NewSource(time.Now().UnixNano()))
- myCommonMethod := func(flag bool) int {
- if flag {
- return r.Intn(c-1) + 1
- } else {
- return r.Intn(c)
- }
- }
- if c >= 2 {
- n = myCommonMethod(true)
- l = c - n
- } else {
- c = l + n
- }
- value := GetRandom(n) + GetLetterRandom(l)
- var array = strings.Split(value, "")
- for i := 0; i < c/2; i++ {
- r1 := myCommonMethod(false)
- r2 := myCommonMethod(false)
- o := array[r1]
- array[r1] = array[r2]
- array[r2] = o
- }
- return strings.Join(array, "")
- }
- /*隐藏部分账号
- *返回手机号:150...70765 邮箱:...shenjun@vip.qq.com
- */
- func EncryCode(value string) string {
- if len(value) == 0 {
- return value
- } else if strings.Contains(value, "@") {
- start := strings.Index(value, "@") / 2
- if start == 0 {
- start++
- }
- value = "...." + string(value[start:])
- } else {
- value = string(value[0:3]) + "..." + string(value[len(value)-4:])
- }
- return value
- }
- //生成32位md5字串
- func GetMd5String(s string) string {
- h := md5.New()
- h.Write([]byte(s))
- return hex.EncodeToString(h.Sum(nil))
- }
- //obj(string,M)转M,查询用到
- func ObjToMap(obj interface{}) *map[string]interface{} {
- data := make(map[string]interface{})
- if s, ok := obj.(string); ok {
- json.Unmarshal([]byte(strings.Replace(s, "'", "\"", -1)), &data)
- } else if s1, ok1 := obj.(map[string]interface{}); ok1 {
- data = s1
- } else if s1, ok1 := obj.(*map[string]interface{}); ok1 {
- return s1
- } else {
- data = nil
- }
- return &data
- }
- /*UTC类型时间转字符串
- *flag==true,日期格式yyyy-mm-dd hh:mm:ss
- *flag==false,日期格式yyyy-mm-dd
- */
- func LongToDate(date interface{}, flag bool) string {
- var int64Date int64
- if l1, ok1 := date.(float64); ok1 {
- int64Date = int64(l1)
- } else if l2, ok2 := date.(int64); ok2 {
- int64Date = l2
- } else if l3, ok3 := date.(int); ok3 {
- int64Date = int64(l3)
- }
- t := time.Unix(int64Date, 0)
- if flag {
- return t.Format("2006-01-02 15:04:05")
- } else {
- return t.Format("2006-01-02")
- }
- }
- func IntAll(num interface{}) int {
- return IntAllDef(num, 0)
- }
- func Int64All(num interface{}) int64 {
- if i, ok := num.(int64); ok {
- return int64(i)
- } else if i0, ok0 := num.(int32); ok0 {
- return int64(i0)
- } else if i1, ok1 := num.(float64); ok1 {
- return int64(i1)
- } else if i2, ok2 := num.(int); ok2 {
- return int64(i2)
- } else if i3, ok3 := num.(float32); ok3 {
- return int64(i3)
- } else if i4, ok4 := num.(string); ok4 {
- i64, _ := strconv.ParseInt(i4, 10, 64)
- //in, _ := strconv.Atoi(i4)
- return i64
- } else if i5, ok5 := num.(int16); ok5 {
- return int64(i5)
- } else if i6, ok6 := num.(int8); ok6 {
- return int64(i6)
- } else if i7, ok7 := num.(*big.Int); ok7 {
- in, _ := strconv.ParseInt(fmt.Sprint(i7), 10, 64)
- return int64(in)
- } else if i8, ok8 := num.(*big.Float); ok8 {
- in, _ := strconv.ParseInt(fmt.Sprint(i8), 10, 64)
- return int64(in)
- } else {
- return 0
- }
- }
- func Float64All(num interface{}) float64 {
- if i, ok := num.(float64); ok {
- return float64(i)
- } else if i0, ok0 := num.(int32); ok0 {
- return float64(i0)
- } else if i1, ok1 := num.(int64); ok1 {
- return float64(i1)
- } else if i2, ok2 := num.(int); ok2 {
- return float64(i2)
- } else if i3, ok3 := num.(float32); ok3 {
- return float64(i3)
- } else if i4, ok4 := num.(string); ok4 {
- in, _ := strconv.ParseFloat(i4, 64)
- return in
- } else if i5, ok5 := num.(int16); ok5 {
- return float64(i5)
- } else if i6, ok6 := num.(int8); ok6 {
- return float64(i6)
- } else if i6, ok6 := num.(uint); ok6 {
- return float64(i6)
- } else if i6, ok6 := num.(uint8); ok6 {
- return float64(i6)
- } else if i6, ok6 := num.(uint16); ok6 {
- return float64(i6)
- } else if i6, ok6 := num.(uint32); ok6 {
- return float64(i6)
- } else if i6, ok6 := num.(uint64); ok6 {
- return float64(i6)
- } else if i7, ok7 := num.(*big.Float); ok7 {
- in, _ := strconv.ParseFloat(fmt.Sprint(i7), 64)
- return float64(in)
- } else if i8, ok8 := num.(*big.Int); ok8 {
- in, _ := strconv.ParseFloat(fmt.Sprint(i8), 64)
- return float64(in)
- } else {
- return 0
- }
- }
- func IntAllDef(num interface{}, defaultNum int) int {
- if i, ok := num.(int); ok {
- return int(i)
- } else if i0, ok0 := num.(int32); ok0 {
- return int(i0)
- } else if i1, ok1 := num.(float64); ok1 {
- return int(i1)
- } else if i2, ok2 := num.(int64); ok2 {
- return int(i2)
- } else if i3, ok3 := num.(float32); ok3 {
- return int(i3)
- } else if i4, ok4 := num.(string); ok4 {
- in, _ := strconv.Atoi(i4)
- return int(in)
- } else if i5, ok5 := num.(int16); ok5 {
- return int(i5)
- } else if i6, ok6 := num.(int8); ok6 {
- return int(i6)
- } else if i7, ok7 := num.(*big.Int); ok7 {
- in, _ := strconv.Atoi(fmt.Sprint(i7))
- return int(in)
- } else if i8, ok8 := num.(*big.Float); ok8 {
- in, _ := strconv.Atoi(fmt.Sprint(i8))
- return int(in)
- } else {
- return defaultNum
- }
- }
- func ObjToString(old interface{}) string {
- if nil == old {
- return ""
- } else {
- r, _ := old.(string)
- return r
- }
- }
- func ObjToStringDef(old interface{}, defaultstr string) string {
- if nil == old {
- return defaultstr
- } else {
- r, _ := old.(string)
- if r == "" {
- return defaultstr
- }
- return r
- }
- }
- //对象数组转成string数组
- func ObjArrToStringArr(old []interface{}) []string {
- if old != nil {
- new := make([]string, len(old))
- for i, v := range old {
- new[i], _ = v.(string)
- }
- return new
- } else {
- return nil
- }
- }
- //对象数组转成map数组
- func ObjArrToMapArr(old []interface{}) []map[string]interface{} {
- if old != nil {
- new := make([]map[string]interface{}, len(old))
- for i, v := range old {
- new[i], _ = v.(map[string]interface{})
- }
- return new
- } else {
- return nil
- }
- }
- //map数组转成对象数组
- func MapArrToObjArr(old []map[string]interface{}) []interface{} {
- if old != nil {
- new := make([]interface{}, len(old))
- for i, v := range old {
- new[i] = v
- }
- return new
- } else {
- return nil
- }
- }
- func SubstrByByte(str string, length int) string {
- bs := []byte(str)[:length]
- bl := 0
- for i := len(bs) - 1; i >= 0; i-- {
- switch {
- case bs[i] >= 0 && bs[i] <= 127:
- return string(bs[:i+1])
- case bs[i] >= 128 && bs[i] <= 191:
- bl++
- case bs[i] >= 192 && bs[i] <= 253:
- cl := 0
- switch {
- case bs[i]&252 == 252:
- cl = 6
- case bs[i]&248 == 248:
- cl = 5
- case bs[i]&240 == 240:
- cl = 4
- case bs[i]&224 == 224:
- cl = 3
- default:
- cl = 2
- }
- if bl+1 == cl {
- return string(bs[:i+cl])
- }
- return string(bs[:i])
- }
- }
- return ""
- }
- func SubString(str string, begin, length int) (substr string) {
- // 将字符串的转换成[]rune
- rs := []rune(str)
- lth := len(rs)
- // 简单的越界判断
- if begin < 0 {
- begin = 0
- }
- if begin >= lth {
- begin = lth
- }
- end := begin + length
- if end > lth {
- end = lth
- }
- // 返回子串
- return string(rs[begin:end])
- }
- //捕获异常
- func Try(fun func(), handler func(interface{})) {
- defer func() {
- if err := recover(); err != nil {
- for skip := 1; ; skip++ {
- _, file, line, ok := runtime.Caller(skip)
- if !ok {
- break
- }
- go log.Printf("%v,%v\n", file, line)
- }
- handler(err)
- }
- }()
- fun()
- }
- //3目运算
- func If(b bool, to, fo interface{}) interface{} {
- if b {
- return to
- } else {
- return fo
- }
- }
- //HashCode值
- func HashCode(uid string) int {
- var h uint32 = 0
- rs := []rune(uid)
- for i := 0; i < len(rs); i++ {
- h = 31*h + uint32(rs[i])
- }
- return int(h)
- }
- //获取离n天的秒差
- func GetDayStartSecond(n int) int64 {
- now := time.Now()
- tom := time.Date(now.Year(), now.Month(), now.Day()+n, 0, 0, 0, 0, time.Local)
- return tom.Unix()
- }
- func InterfaceArrTointArr(arr []interface{}) []int {
- tmp := make([]int, 0)
- for _, v := range arr {
- tmp = append(tmp, int(v.(float64)))
- }
- return tmp
- }
- func InterfaceArrToint64Arr(arr []interface{}) []int64 {
- tmp := make([]int64, 0)
- for _, v := range arr {
- tmp = append(tmp, int64(v.(float64)))
- }
- return tmp
- }
- func GetSubDay(t1 int64) int {
- tt1 := time.Unix(t1, 0)
- tt2 := time.Now()
- nt1 := time.Date(tt1.Year(), tt1.Month(), tt1.Day(), 0, 0, 0, 0, time.Local)
- nt2 := time.Date(tt2.Year(), tt2.Month(), tt2.Day(), 0, 0, 0, 0, time.Local)
- return int((nt1.Unix() - nt2.Unix()) / 86400)
- }
- func StartWith(value, str string) bool {
- ok, _ := regexp.MatchString("^"+str, value)
- return ok
- }
- func EndWith(value, str string) bool {
- ok, _ := regexp.MatchString(str+"$", value)
- return ok
- }
- //出错拦截
- func Catch() {
- if r := recover(); r != nil {
- log.Println(r)
- for skip := 0; ; skip++ {
- _, file, line, ok := runtime.Caller(skip)
- if !ok {
- break
- }
- go log.Printf("%v,%v\n", file, line)
- }
- }
- }
- func ConvertFileSize(s int) string {
- size := float64(s)
- var kb float64 = 1024
- var mb float64 = kb * 1024
- var gb float64 = mb * 1024
- if size >= gb {
- return fmt.Sprintf("%.1f GB", float64(size/gb))
- } else if size >= mb {
- f := float64(size / mb)
- if f > 100 {
- return fmt.Sprintf("%.0f MB", f)
- }
- return fmt.Sprintf("%.1f MB", f)
- } else if size >= kb {
- f := float64(size / kb)
- if f > 100 {
- return fmt.Sprintf("%.0f KB", f)
- }
- return fmt.Sprintf("%.1f KB", f)
- }
- return fmt.Sprintf("%d B", s)
- }
- //MD5签名
- func WxSign(format string, param ...interface{}) string {
- data := fmt.Sprintf(format, param...)
- h := md5.New()
- h.Write([]byte(data))
- sign := strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
- return sign
- }
- //计算时差
- func TimeDiff(date time.Time) string {
- var date1 = date //开始时间
- var date2 = time.Now() //结束时间
- var date3 = date2.Unix() - date1.Unix() //时间差的毫秒数
- //计算出相差天数
- var days = math.Floor(float64(date3 / (24 * 3600)))
- //计算出小时数
- var leave1 = date3 % (24 * 3600) //计算天数后剩余的毫秒数
- var hours = math.Floor(float64(leave1 / (3600)))
- //计算相差分钟数
- var leave2 = leave1 % (3600) //计算小时数后剩余的毫秒数
- var minutes = math.Floor(float64(leave2 / (60)))
- //计算相差秒数
- var td = "30秒前"
- if days > 0 {
- if days > 10 {
- if date1.Year() < date2.Year() {
- td = date4.FormatDate(&date, date4.Date_Short_Layout)
- } else {
- td = date4.FormatDate(&date, date4.Date_Small_Layout)
- }
- } else {
- td = fmt.Sprint(days) + "天前"
- }
- } else if hours > 0 {
- td = fmt.Sprint(hours) + "小时前"
- } else if minutes > 0 {
- td = fmt.Sprint(minutes) + "分钟前"
- }
- return td
- }
- func FloatFormat(tmp float64, n int) float64 {
- fs := fmt.Sprintf("%."+fmt.Sprint(n)+"f", tmp)
- f, _ := strconv.ParseFloat(fs, 64)
- return f
- }
- //生成微信支付的签名
- func CreateWxSign(afterStr string, obj interface{}, filter ...string) string {
- filter = append(filter, "sign", "xml")
- keys := []string{}
- m := make(map[string]string)
- t := reflect.TypeOf(obj)
- v := reflect.ValueOf(obj)
- k := t.Kind()
- if t.Kind() == reflect.Ptr {
- t = t.Elem()
- k = t.Kind()
- v = v.Elem()
- }
- if k == reflect.Map {
- for _, key := range v.MapKeys() {
- keys = append(keys, key.String())
- m[key.String()] = fmt.Sprint(v.MapIndex(key).Interface())
- }
- } else if k == reflect.Struct {
- for n := 0; n < t.NumField(); n++ {
- tagName := t.Field(n).Tag.Get("xml")
- if tagName == "" {
- tagName = t.Field(n).Tag.Get("json")
- }
- if tagName == "" {
- tagName = t.Field(n).Name
- }
- keys = append(keys, tagName)
- m[tagName] = fmt.Sprint(v.Field(n))
- }
- }
- sort.Strings(keys)
- vs := []string{}
- L:
- for _, v := range keys {
- for _, f := range filter {
- if f == v {
- continue L
- }
- }
- if strings.TrimSpace(m[v]) == "" {
- continue
- }
- vs = append(vs, fmt.Sprintf("%s=%s", v, m[v]))
- }
- return WxSign(strings.Join(vs, "&") + afterStr)
- }
- //简单的xml转map,只有一个层级,没有多层嵌套
- func XmlToMap(input string) map[string]string {
- var t xml.Token
- var err error
- inputReader := strings.NewReader(input)
- decoder := xml.NewDecoder(inputReader)
- isStart := false
- nodeName := ""
- m := make(map[string]string)
- for t, err = decoder.Token(); err == nil; t, err = decoder.Token() {
- switch token := t.(type) {
- // 处理元素开始(标签)
- case xml.StartElement:
- isStart = true
- nodeName = token.Name.Local
- // 处理元素结束(标签)
- case xml.EndElement:
- isStart = false
- // 处理字符数据(这里就是元素的文本)
- case xml.CharData:
- if isStart {
- m[nodeName] = string([]byte(token))
- }
- default:
- // ...
- }
- }
- return m
- }
- func SimpleCrontab(flag bool, c string, f func()) {
- array := strings.Split(c, ":")
- if len(array) != 2 {
- log.Fatalln("定时任务参数错误!", c)
- }
- if flag {
- go f()
- }
- now := time.Now()
- t := time.Date(now.Year(), now.Month(), now.Day(), IntAll(array[0]), IntAll(array[1]), 0, 0, time.Local)
- if t.Before(now) {
- t = t.AddDate(0, 0, 1)
- }
- sub := t.Sub(now)
- log.Println(c, "run after", sub)
- timer := time.NewTimer(sub)
- for {
- select {
- case <-timer.C:
- go f()
- log.Println(c, "run after", 24*time.Hour)
- timer.Reset(24 * time.Hour)
- }
- }
- }
- //v保留n为小数,n后的四舍五入
- func RetainDecimal(v float64, n int) float64 {
- n10 := math.Pow10(n)
- return math.Trunc((v+0.5/n10)*n10) / n10
- }
|