|
@@ -0,0 +1,709 @@
|
|
|
+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
|
|
|
+}
|