common.go 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571
  1. package utils
  2. import (
  3. "bufio"
  4. "bytes"
  5. "crypto/hmac"
  6. "crypto/md5"
  7. "crypto/sha1"
  8. "encoding/base64"
  9. "encoding/hex"
  10. "encoding/json"
  11. "errors"
  12. "fmt"
  13. "html"
  14. "image"
  15. "image/png"
  16. "io"
  17. "math"
  18. "math/rand"
  19. "net"
  20. "net/http"
  21. "net/url"
  22. "os"
  23. "os/exec"
  24. "path"
  25. "regexp"
  26. "strconv"
  27. "strings"
  28. "time"
  29. "github.com/PuerkitoBio/goquery"
  30. "github.com/microcosm-cc/bluemonday"
  31. "github.com/shopspring/decimal"
  32. "github.com/spaolacci/murmur3"
  33. xhtml "golang.org/x/net/html"
  34. )
  35. // 随机数种子
  36. var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
  37. func GetRandString(size int) string {
  38. allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "!", "@", "#", "$", "%", "^", "&", "*"}
  39. randomSb := ""
  40. digitSize := len(allLetterDigit)
  41. for i := 0; i < size; i++ {
  42. randomSb += allLetterDigit[rnd.Intn(digitSize)]
  43. }
  44. return randomSb
  45. }
  46. func GetRandStringNoSpecialChar(size int) string {
  47. allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
  48. randomSb := ""
  49. digitSize := len(allLetterDigit)
  50. for i := 0; i < size; i++ {
  51. randomSb += allLetterDigit[rnd.Intn(digitSize)]
  52. }
  53. return randomSb
  54. }
  55. func StringsToJSON(str string) string {
  56. rs := []rune(str)
  57. jsons := ""
  58. for _, r := range rs {
  59. rint := int(r)
  60. if rint < 128 {
  61. jsons += string(r)
  62. } else {
  63. jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
  64. }
  65. }
  66. return jsons
  67. }
  68. // 序列化
  69. func ToString(v interface{}) string {
  70. data, _ := json.Marshal(v)
  71. return string(data)
  72. }
  73. // md5加密
  74. func MD5(data string) string {
  75. m := md5.Sum([]byte(data))
  76. return hex.EncodeToString(m[:])
  77. }
  78. // HmacMd5 HmacMd5加密
  79. func HmacMd5(key, data string) string {
  80. h := hmac.New(md5.New, []byte(key))
  81. h.Write([]byte(data))
  82. return hex.EncodeToString(h.Sum([]byte("")))
  83. }
  84. // 获取数字随机字符
  85. func GetRandDigit(n int) string {
  86. return fmt.Sprintf("%0"+strconv.Itoa(n)+"d", rnd.Intn(int(math.Pow10(n))))
  87. }
  88. // 获取随机数
  89. func GetRandNumber(n int) int {
  90. return rnd.Intn(n)
  91. }
  92. func GetRandInt(min, max int) int {
  93. if min >= max || min == 0 || max == 0 {
  94. return max
  95. }
  96. return rand.Intn(max-min) + min
  97. }
  98. func GetToday(format string) string {
  99. today := time.Now().Format(format)
  100. return today
  101. }
  102. // 获取今天剩余秒数
  103. func GetTodayLastSecond() time.Duration {
  104. today := GetToday(FormatDate) + " 23:59:59"
  105. end, _ := time.ParseInLocation(FormatDateTime, today, time.Local)
  106. return time.Duration(end.Unix()-time.Now().Local().Unix()) * time.Second
  107. }
  108. // 处理出生日期函数
  109. func GetBrithDate(idcard string) string {
  110. l := len(idcard)
  111. var s string
  112. if l == 15 {
  113. s = "19" + idcard[6:8] + "-" + idcard[8:10] + "-" + idcard[10:12]
  114. return s
  115. }
  116. if l == 18 {
  117. s = idcard[6:10] + "-" + idcard[10:12] + "-" + idcard[12:14]
  118. return s
  119. }
  120. return GetToday(FormatDate)
  121. }
  122. // 处理性别
  123. func WhichSexByIdcard(idcard string) string {
  124. var sexs = [2]string{"女", "男"}
  125. length := len(idcard)
  126. if length == 18 {
  127. sex, _ := strconv.Atoi(string(idcard[16]))
  128. return sexs[sex%2]
  129. } else if length == 15 {
  130. sex, _ := strconv.Atoi(string(idcard[14]))
  131. return sexs[sex%2]
  132. }
  133. return "男"
  134. }
  135. // 截取小数点后几位
  136. func SubFloatToString(f float64, m int) string {
  137. n := strconv.FormatFloat(f, 'f', -1, 64)
  138. if n == "" {
  139. return ""
  140. }
  141. if m >= len(n) {
  142. return n
  143. }
  144. newn := strings.Split(n, ".")
  145. if m == 0 {
  146. return newn[0]
  147. }
  148. if len(newn) < 2 || m >= len(newn[1]) {
  149. return n
  150. }
  151. return newn[0] + "." + newn[1][:m]
  152. }
  153. // 截取小数点后几位
  154. func SubFloatToFloat(f float64, m int) float64 {
  155. newn := SubFloatToString(f, m)
  156. newf, _ := strconv.ParseFloat(newn, 64)
  157. return newf
  158. }
  159. // 截取小数点后几位
  160. func SubFloatToFloatStr(f float64, m int) string {
  161. newn := SubFloatToString(f, m)
  162. return newn
  163. }
  164. // 获取相差时间-年
  165. func GetYearDiffer(start_time, end_time string) int {
  166. t1, _ := time.ParseInLocation("2006-01-02", start_time, time.Local)
  167. t2, _ := time.ParseInLocation("2006-01-02", end_time, time.Local)
  168. age := t2.Year() - t1.Year()
  169. if t2.Month() < t1.Month() || (t2.Month() == t1.Month() && t2.Day() < t1.Day()) {
  170. age--
  171. }
  172. return age
  173. }
  174. // 获取相差时间-秒
  175. func GetSecondDifferByTime(start_time, end_time time.Time) int64 {
  176. diff := end_time.Unix() - start_time.Unix()
  177. return diff
  178. }
  179. func FixFloat(f float64, m int) float64 {
  180. newn := SubFloatToString(f+0.00000001, m)
  181. newf, _ := strconv.ParseFloat(newn, 64)
  182. return newf
  183. }
  184. // 将字符串数组转化为逗号分割的字符串形式 ["str1","str2","str3"] >>> "str1,str2,str3"
  185. func StrListToString(strList []string) (str string) {
  186. if len(strList) > 0 {
  187. for k, v := range strList {
  188. if k == 0 {
  189. str = v
  190. } else {
  191. str = str + "," + v
  192. }
  193. }
  194. return
  195. }
  196. return ""
  197. }
  198. // Token
  199. func GetToken() string {
  200. randStr := GetRandString(64)
  201. token := MD5(randStr + Md5Key)
  202. tokenLen := 64 - len(token)
  203. return strings.ToUpper(token + GetRandString(tokenLen))
  204. }
  205. // 数据没有记录
  206. func ErrNoRow() string {
  207. return "<QuerySeter> no row found"
  208. }
  209. // 校验邮箱格式
  210. func ValidateEmailFormatat(email string) bool {
  211. reg := regexp.MustCompile(RegularEmail)
  212. return reg.MatchString(email)
  213. }
  214. // 验证是否是手机号
  215. func ValidateMobileFormatat(mobileNum string) bool {
  216. reg := regexp.MustCompile(RegularMobile)
  217. return reg.MatchString(mobileNum)
  218. }
  219. // 判断文件是否存在
  220. func FileIsExist(filePath string) bool {
  221. _, err := os.Stat(filePath)
  222. return err == nil || os.IsExist(err)
  223. }
  224. // 获取图片扩展名
  225. func GetImgExt(file string) (ext string, err error) {
  226. var headerByte []byte
  227. headerByte = make([]byte, 8)
  228. fd, err := os.Open(file)
  229. if err != nil {
  230. return "", err
  231. }
  232. defer fd.Close()
  233. _, err = fd.Read(headerByte)
  234. if err != nil {
  235. return "", err
  236. }
  237. xStr := fmt.Sprintf("%x", headerByte)
  238. switch {
  239. case xStr == "89504e470d0a1a0a":
  240. ext = ".png"
  241. case xStr == "0000010001002020":
  242. ext = ".ico"
  243. case xStr == "0000020001002020":
  244. ext = ".cur"
  245. case xStr[:12] == "474946383961" || xStr[:12] == "474946383761":
  246. ext = ".gif"
  247. case xStr[:10] == "0000020000" || xStr[:10] == "0000100000":
  248. ext = ".tga"
  249. case xStr[:8] == "464f524d":
  250. ext = ".iff"
  251. case xStr[:8] == "52494646":
  252. ext = ".ani"
  253. case xStr[:4] == "4d4d" || xStr[:4] == "4949":
  254. ext = ".tiff"
  255. case xStr[:4] == "424d":
  256. ext = ".bmp"
  257. case xStr[:4] == "ffd8":
  258. ext = ".jpg"
  259. case xStr[:2] == "0a":
  260. ext = ".pcx"
  261. default:
  262. ext = ""
  263. }
  264. return ext, nil
  265. }
  266. // 保存图片
  267. func SaveImage(path string, img image.Image) (err error) {
  268. //需要保持的文件
  269. imgfile, err := os.Create(path)
  270. defer imgfile.Close()
  271. // 以PNG格式保存文件
  272. err = png.Encode(imgfile, img)
  273. return err
  274. }
  275. // 下载图片
  276. func DownloadImage(imgUrl string) (filePath string, err error) {
  277. imgPath := "./static/imgs/"
  278. fileName := path.Base(imgUrl)
  279. res, err := http.Get(imgUrl)
  280. if err != nil {
  281. fmt.Println("A error occurred!")
  282. return
  283. }
  284. defer res.Body.Close()
  285. // 获得get请求响应的reader对象
  286. reader := bufio.NewReaderSize(res.Body, 32*1024)
  287. filePath = imgPath + fileName
  288. file, err := os.Create(filePath)
  289. if err != nil {
  290. return
  291. }
  292. // 获得文件的writer对象
  293. writer := bufio.NewWriter(file)
  294. written, _ := io.Copy(writer, reader)
  295. fmt.Printf("Total length: %d \n", written)
  296. return
  297. }
  298. // 保存base64数据为文件
  299. func SaveBase64ToFile(content, path string) error {
  300. data, err := base64.StdEncoding.DecodeString(content)
  301. if err != nil {
  302. return err
  303. }
  304. f, err := os.Create(path)
  305. defer f.Close()
  306. if err != nil {
  307. return err
  308. }
  309. f.Write(data)
  310. return nil
  311. }
  312. func SaveBase64ToFileBySeek(content, path string) (err error) {
  313. data, err := base64.StdEncoding.DecodeString(content)
  314. exist, err := PathExists(path)
  315. if err != nil {
  316. return
  317. }
  318. if !exist {
  319. f, err := os.Create(path)
  320. if err != nil {
  321. return err
  322. }
  323. n, _ := f.Seek(0, 2)
  324. // 从末尾的偏移量开始写入内容
  325. _, err = f.WriteAt([]byte(data), n)
  326. defer f.Close()
  327. } else {
  328. f, err := os.OpenFile(path, os.O_WRONLY, 0644)
  329. if err != nil {
  330. return err
  331. }
  332. n, _ := f.Seek(0, 2)
  333. // 从末尾的偏移量开始写入内容
  334. _, err = f.WriteAt([]byte(data), n)
  335. defer f.Close()
  336. }
  337. return nil
  338. }
  339. func PathExists(path string) (bool, error) {
  340. _, err := os.Stat(path)
  341. if err == nil {
  342. return true, nil
  343. }
  344. if os.IsNotExist(err) {
  345. return false, nil
  346. }
  347. return false, err
  348. }
  349. func StartIndex(page, pagesize int) int {
  350. if page > 1 {
  351. return (page - 1) * pagesize
  352. }
  353. return 0
  354. }
  355. func PageCount(count, pagesize int) int {
  356. if count%pagesize > 0 {
  357. return count/pagesize + 1
  358. } else {
  359. return count / pagesize
  360. }
  361. }
  362. func TrimHtml(src string) string {
  363. //将HTML标签全转换成小写
  364. re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
  365. src = re.ReplaceAllStringFunc(src, strings.ToLower)
  366. re, _ = regexp.Compile("\\<img[\\S\\s]+?\\>")
  367. src = re.ReplaceAllString(src, "")
  368. re, _ = regexp.Compile("class[\\S\\s]+?>")
  369. src = re.ReplaceAllString(src, "")
  370. re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
  371. src = re.ReplaceAllString(src, "")
  372. src = strings.ReplaceAll(src, "&nbsp;", " ")
  373. return strings.TrimSpace(src)
  374. }
  375. //1556164246 -> 2019-04-25 03:50:46 +0000
  376. //timestamp
  377. func TimeToTimestamp() {
  378. fmt.Println(time.Unix(1556164246, 0).Format("2006-01-02 15:04:05"))
  379. }
  380. func ToUnicode(text string) string {
  381. textQuoted := strconv.QuoteToASCII(text)
  382. textUnquoted := textQuoted[1 : len(textQuoted)-1]
  383. return textUnquoted
  384. }
  385. func VersionToInt(version string) int {
  386. version = strings.Replace(version, ".", "", -1)
  387. n, _ := strconv.Atoi(version)
  388. return n
  389. }
  390. func IsCheckInList(list []int, s int) bool {
  391. for _, v := range list {
  392. if v == s {
  393. return true
  394. }
  395. }
  396. return false
  397. }
  398. func round(num float64) int {
  399. return int(num + math.Copysign(0.5, num))
  400. }
  401. func toFixed(num float64, precision int) float64 {
  402. output := math.Pow(10, float64(precision))
  403. return float64(round(num*output)) / output
  404. }
  405. // GetWilsonScore returns Wilson Score
  406. func GetWilsonScore(p, n float64) float64 {
  407. if p == 0 && n == 0 {
  408. return 0
  409. }
  410. return toFixed(((p+1.9208)/(p+n)-1.96*math.Sqrt(p*n/(p+n)+0.9604)/(p+n))/(1+3.8416/(p+n)), 2)
  411. }
  412. // 将中文数字转化成数字,比如 第三百四十五章,返回第345章 不支持一亿及以上
  413. func ChangeWordsToNum(str string) (numStr string) {
  414. words := ([]rune)(str)
  415. num := 0
  416. n := 0
  417. for i := 0; i < len(words); i++ {
  418. word := string(words[i : i+1])
  419. switch word {
  420. case "万":
  421. if n == 0 {
  422. n = 1
  423. }
  424. n = n * 10000
  425. num = num*10000 + n
  426. n = 0
  427. case "千":
  428. if n == 0 {
  429. n = 1
  430. }
  431. n = n * 1000
  432. num += n
  433. n = 0
  434. case "百":
  435. if n == 0 {
  436. n = 1
  437. }
  438. n = n * 100
  439. num += n
  440. n = 0
  441. case "十":
  442. if n == 0 {
  443. n = 1
  444. }
  445. n = n * 10
  446. num += n
  447. n = 0
  448. case "一":
  449. n += 1
  450. case "二":
  451. n += 2
  452. case "三":
  453. n += 3
  454. case "四":
  455. n += 4
  456. case "五":
  457. n += 5
  458. case "六":
  459. n += 6
  460. case "七":
  461. n += 7
  462. case "八":
  463. n += 8
  464. case "九":
  465. n += 9
  466. case "零":
  467. default:
  468. if n > 0 {
  469. num += n
  470. n = 0
  471. }
  472. if num == 0 {
  473. numStr += word
  474. } else {
  475. numStr += strconv.Itoa(num) + word
  476. num = 0
  477. }
  478. }
  479. }
  480. if n > 0 {
  481. num += n
  482. n = 0
  483. }
  484. if num != 0 {
  485. numStr += strconv.Itoa(num)
  486. }
  487. return
  488. }
  489. func Sha1(data string) string {
  490. sha1 := sha1.New()
  491. sha1.Write([]byte(data))
  492. return hex.EncodeToString(sha1.Sum([]byte("")))
  493. }
  494. func GetVideoPlaySeconds(videoPath string) (playSeconds float64, err error) {
  495. cmd := `ffmpeg -i ` + videoPath + ` 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//`
  496. out, err := exec.Command("bash", "-c", cmd).Output()
  497. if err != nil {
  498. return
  499. }
  500. outTimes := string(out)
  501. fmt.Println("outTimes:", outTimes)
  502. if outTimes != "" {
  503. timeArr := strings.Split(outTimes, ":")
  504. h := timeArr[0]
  505. m := timeArr[1]
  506. s := timeArr[2]
  507. hInt, err := strconv.Atoi(h)
  508. if err != nil {
  509. return playSeconds, err
  510. }
  511. mInt, err := strconv.Atoi(m)
  512. if err != nil {
  513. return playSeconds, err
  514. }
  515. s = strings.Trim(s, " ")
  516. s = strings.Trim(s, "\n")
  517. sInt, err := strconv.ParseFloat(s, 64)
  518. if err != nil {
  519. return playSeconds, err
  520. }
  521. playSeconds = float64(hInt)*3600 + float64(mInt)*60 + float64(sInt)
  522. }
  523. return
  524. }
  525. func GetMaxTradeCode(tradeCode string) (maxTradeCode string, err error) {
  526. tradeCode = strings.Replace(tradeCode, "W", "", -1)
  527. tradeCode = strings.Trim(tradeCode, " ")
  528. tradeCodeInt, err := strconv.Atoi(tradeCode)
  529. if err != nil {
  530. return
  531. }
  532. tradeCodeInt = tradeCodeInt + 1
  533. maxTradeCode = fmt.Sprintf("W%06d", tradeCodeInt)
  534. return
  535. }
  536. // excel日期字段格式化 yyyy-mm-dd
  537. func ConvertToFormatDay(excelDaysString string) string {
  538. // 2006-01-02 距离 1900-01-01的天数
  539. baseDiffDay := 38719 //在网上工具计算的天数需要加2天,什么原因没弄清楚
  540. curDiffDay := excelDaysString
  541. b, _ := strconv.Atoi(curDiffDay)
  542. // 获取excel的日期距离2006-01-02的天数
  543. realDiffDay := b - baseDiffDay
  544. //fmt.Println("realDiffDay:",realDiffDay)
  545. // 距离2006-01-02 秒数
  546. realDiffSecond := realDiffDay * 24 * 3600
  547. //fmt.Println("realDiffSecond:",realDiffSecond)
  548. // 2006-01-02 15:04:05距离1970-01-01 08:00:00的秒数 网上工具可查出
  549. baseOriginSecond := 1136185445
  550. resultTime := time.Unix(int64(baseOriginSecond+realDiffSecond), 0).Format("2006-01-02")
  551. return resultTime
  552. }
  553. // GetDaysDiff1900 计算日期距离1900-01-01的天数
  554. func GetDaysDiff1900(date string) int {
  555. // 将字符串转换为时间类型
  556. //从1899年12月30日开始是因为Excel的日期计算是基于1900年1月1日的,而1900年并不是闰年,因此Excel日期计算存在一个错误。为了修正这个错误,
  557. //我们将时间回溯到1899年12月30日,这样在进行日期计算时可以正确地处理Excel日期。
  558. tStart, err := time.ParseInLocation(FormatDate, "1899-12-30", time.Local)
  559. if err != nil {
  560. return 0
  561. }
  562. tEnd, err := time.ParseInLocation(FormatDate, date, time.Local)
  563. if err != nil {
  564. return 0
  565. }
  566. // 计算两个日期之间的天数差值
  567. duration := tEnd.Sub(tStart).Hours() / 24
  568. days := int(duration)
  569. return days
  570. }
  571. func CheckPwd(pwd string) bool {
  572. compile := `([0-9a-z]+){6,12}|(a-z0-9]+){6,12}`
  573. reg := regexp.MustCompile(compile)
  574. flag := reg.MatchString(pwd)
  575. return flag
  576. }
  577. func GetMonthStartAndEnd(myYear string, myMonth string) (startDate, endDate string) {
  578. // 数字月份必须前置补零
  579. if len(myMonth) == 1 {
  580. myMonth = "0" + myMonth
  581. }
  582. yInt, _ := strconv.Atoi(myYear)
  583. timeLayout := "2006-01-02 15:04:05"
  584. loc, _ := time.LoadLocation("Local")
  585. theTime, _ := time.ParseInLocation(timeLayout, myYear+"-"+myMonth+"-01 00:00:00", loc)
  586. newMonth := theTime.Month()
  587. t1 := time.Date(yInt, newMonth, 1, 0, 0, 0, 0, time.Local).Format("2006-01-02")
  588. t2 := time.Date(yInt, newMonth+1, 0, 0, 0, 0, 0, time.Local).Format("2006-01-02")
  589. return t1, t2
  590. }
  591. // TrimStr 移除字符串中的空格
  592. func TrimStr(str string) (str2 string) {
  593. if str == "" {
  594. return str
  595. }
  596. return strings.Replace(str, " ", "", -1)
  597. }
  598. // TrimLRStr 移除字符串前后的空格
  599. func TrimLRStr(str string) (str2 string) {
  600. if str == "" {
  601. return str
  602. }
  603. str2 = strings.TrimLeft(str, " ")
  604. str2 = strings.TrimRight(str2, " ")
  605. return
  606. }
  607. // 字符串转换为time
  608. func StrTimeToTime(strTime string) time.Time {
  609. timeLayout := "2006-01-02 15:04:05" //转化所需模板
  610. loc, _ := time.LoadLocation("Local") //重要:获取时区
  611. resultTime, _ := time.ParseInLocation(timeLayout, strTime, loc)
  612. return resultTime
  613. }
  614. // 字符串类型时间转周几
  615. func StrDateTimeToWeek(strTime string) string {
  616. var WeekDayMap = map[string]string{
  617. "Monday": "周一",
  618. "Tuesday": "周二",
  619. "Wednesday": "周三",
  620. "Thursday": "周四",
  621. "Friday": "周五",
  622. "Saturday": "周六",
  623. "Sunday": "周日",
  624. }
  625. var ctime = StrTimeToTime(strTime).Format("2006-01-02")
  626. startday, _ := time.Parse("2006-01-02", ctime)
  627. staweek_int := startday.Weekday().String()
  628. return WeekDayMap[staweek_int]
  629. }
  630. // EnWeekToCnWeek 英文周几转中文周几
  631. func EnWeekToCnWeek(enWeekStr string) string {
  632. var WeekDayMap = map[string]string{
  633. "Monday": "周一",
  634. "Tuesday": "周二",
  635. "Wednesday": "周三",
  636. "Thursday": "周四",
  637. "Friday": "周五",
  638. "Saturday": "周六",
  639. "Sunday": "周日",
  640. }
  641. cnWeekStr, ok := WeekDayMap[enWeekStr]
  642. if !ok {
  643. cnWeekStr = `周一`
  644. }
  645. return cnWeekStr
  646. }
  647. // 时间格式转年月日字符串
  648. func TimeToStrYmd(time2 time.Time) string {
  649. var Ymd string
  650. year := time2.Year()
  651. month := time2.Format("1")
  652. day1 := time.Now().Day()
  653. Ymd = strconv.Itoa(year) + "年" + month + "月" + strconv.Itoa(day1) + "日"
  654. return Ymd
  655. }
  656. // 时间格式去掉时分秒
  657. func TimeRemoveHms(strTime string) string {
  658. var Ymd string
  659. var resultTime = StrTimeToTime(strTime)
  660. year := resultTime.Year()
  661. month := resultTime.Format("01")
  662. day1 := resultTime.Day()
  663. if day1 < 10 {
  664. Ymd = strconv.Itoa(year) + "." + month + ".0" + strconv.Itoa(day1)
  665. } else {
  666. Ymd = strconv.Itoa(year) + "." + month + "." + strconv.Itoa(day1)
  667. }
  668. return Ymd
  669. }
  670. // 时间格式去掉时分秒
  671. func TimeRemoveHms2(strTime string) string {
  672. var Ymd string
  673. var resultTime = StrTimeToTime(strTime)
  674. year := resultTime.Year()
  675. month := resultTime.Format("01")
  676. day1 := resultTime.Day()
  677. if day1 < 10 {
  678. Ymd = strconv.Itoa(year) + "-" + month + "-0" + strconv.Itoa(day1)
  679. } else {
  680. Ymd = strconv.Itoa(year) + "-" + month + "-" + strconv.Itoa(day1)
  681. }
  682. return Ymd
  683. }
  684. // 文章上一次编辑时间
  685. func ArticleLastTime(strTime string) string {
  686. var newTime string
  687. stamp, _ := time.ParseInLocation("2006-01-02 15:04:05", strTime, time.Local)
  688. diffTime := time.Now().Unix() - stamp.Unix()
  689. if diffTime <= 60 {
  690. newTime = "当前"
  691. } else if diffTime < 60*60 {
  692. newTime = strconv.FormatInt(diffTime/60, 10) + "分钟前"
  693. } else if diffTime < 24*60*60 {
  694. newTime = strconv.FormatInt(diffTime/(60*60), 10) + "小时前"
  695. } else if diffTime < 30*24*60*60 {
  696. newTime = strconv.FormatInt(diffTime/(24*60*60), 10) + "天前"
  697. } else if diffTime < 12*30*24*60*60 {
  698. newTime = strconv.FormatInt(diffTime/(30*24*60*60), 10) + "月前"
  699. } else {
  700. newTime = "1年前"
  701. }
  702. return newTime
  703. }
  704. // 人民币小写转大写
  705. func ConvertNumToCny(num float64) (str string, err error) {
  706. strNum := strconv.FormatFloat(num*100, 'f', 0, 64)
  707. sliceUnit := []string{"仟", "佰", "拾", "亿", "仟", "佰", "拾", "万", "仟", "佰", "拾", "元", "角", "分"}
  708. // log.Println(sliceUnit[:len(sliceUnit)-2])
  709. s := sliceUnit[len(sliceUnit)-len(strNum):]
  710. upperDigitUnit := map[string]string{"0": "零", "1": "壹", "2": "贰", "3": "叁", "4": "肆", "5": "伍", "6": "陆", "7": "柒", "8": "捌", "9": "玖"}
  711. for k, v := range strNum[:] {
  712. str = str + upperDigitUnit[string(v)] + s[k]
  713. }
  714. reg, err := regexp.Compile(`零角零分$`)
  715. str = reg.ReplaceAllString(str, "整")
  716. reg, err = regexp.Compile(`零角`)
  717. str = reg.ReplaceAllString(str, "零")
  718. reg, err = regexp.Compile(`零分$`)
  719. str = reg.ReplaceAllString(str, "整")
  720. reg, err = regexp.Compile(`零[仟佰拾]`)
  721. str = reg.ReplaceAllString(str, "零")
  722. reg, err = regexp.Compile(`零{2,}`)
  723. str = reg.ReplaceAllString(str, "零")
  724. reg, err = regexp.Compile(`零亿`)
  725. str = reg.ReplaceAllString(str, "亿")
  726. reg, err = regexp.Compile(`零万`)
  727. str = reg.ReplaceAllString(str, "万")
  728. reg, err = regexp.Compile(`零*元`)
  729. str = reg.ReplaceAllString(str, "元")
  730. reg, err = regexp.Compile(`亿零{0, 3}万`)
  731. str = reg.ReplaceAllString(str, "^元")
  732. reg, err = regexp.Compile(`零元`)
  733. str = reg.ReplaceAllString(str, "零")
  734. return
  735. }
  736. // GetNowWeekMonday 获取本周周一的时间
  737. func GetNowWeekMonday() time.Time {
  738. offset := int(time.Monday - time.Now().Weekday())
  739. if offset == 1 { //正好是周日,但是按照中国人的理解,周日是一周最后一天,而不是一周开始的第一天
  740. offset = -6
  741. }
  742. mondayTime := time.Now().AddDate(0, 0, offset)
  743. mondayTime = time.Date(mondayTime.Year(), mondayTime.Month(), mondayTime.Day(), 0, 0, 0, 0, mondayTime.Location())
  744. return mondayTime
  745. }
  746. // GetNowWeekLastDay 获取本周最后一天的时间
  747. func GetNowWeekLastDay() time.Time {
  748. offset := int(time.Monday - time.Now().Weekday())
  749. if offset == 1 { //正好是周日,但是按照中国人的理解,周日是一周最后一天,而不是一周开始的第一天
  750. offset = -6
  751. }
  752. firstDayTime := time.Now().AddDate(0, 0, offset)
  753. firstDayTime = time.Date(firstDayTime.Year(), firstDayTime.Month(), firstDayTime.Day(), 0, 0, 0, 0, firstDayTime.Location()).AddDate(0, 0, 6)
  754. lastDayTime := time.Date(firstDayTime.Year(), firstDayTime.Month(), firstDayTime.Day(), 23, 59, 59, 0, firstDayTime.Location())
  755. return lastDayTime
  756. }
  757. // GetNowMonthFirstDay 获取本月第一天的时间
  758. func GetNowMonthFirstDay() time.Time {
  759. nowMonthFirstDay := time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.Now().Location())
  760. return nowMonthFirstDay
  761. }
  762. // GetNowMonthLastDay 获取本月最后一天的时间
  763. func GetNowMonthLastDay() time.Time {
  764. nowMonthLastDay := time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  765. nowMonthLastDay = time.Date(nowMonthLastDay.Year(), nowMonthLastDay.Month(), nowMonthLastDay.Day(), 23, 59, 59, 0, nowMonthLastDay.Location())
  766. return nowMonthLastDay
  767. }
  768. // GetNowQuarterFirstDay 获取本季度第一天的时间
  769. func GetNowQuarterFirstDay() time.Time {
  770. month := int(time.Now().Month())
  771. var nowQuarterFirstDay time.Time
  772. if month >= 1 && month <= 3 {
  773. //1月1号
  774. nowQuarterFirstDay = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
  775. } else if month >= 4 && month <= 6 {
  776. //4月1号
  777. nowQuarterFirstDay = time.Date(time.Now().Year(), 4, 1, 0, 0, 0, 0, time.Now().Location())
  778. } else if month >= 7 && month <= 9 {
  779. nowQuarterFirstDay = time.Date(time.Now().Year(), 7, 1, 0, 0, 0, 0, time.Now().Location())
  780. } else {
  781. nowQuarterFirstDay = time.Date(time.Now().Year(), 10, 1, 0, 0, 0, 0, time.Now().Location())
  782. }
  783. return nowQuarterFirstDay
  784. }
  785. // GetNowQuarterLastDay 获取本季度最后一天的时间
  786. func GetNowQuarterLastDay() time.Time {
  787. month := int(time.Now().Month())
  788. var nowQuarterLastDay time.Time
  789. if month >= 1 && month <= 3 {
  790. //03-31 23:59:59
  791. nowQuarterLastDay = time.Date(time.Now().Year(), 3, 31, 23, 59, 59, 0, time.Now().Location())
  792. } else if month >= 4 && month <= 6 {
  793. //06-30 23:59:59
  794. nowQuarterLastDay = time.Date(time.Now().Year(), 6, 30, 23, 59, 59, 0, time.Now().Location())
  795. } else if month >= 7 && month <= 9 {
  796. //09-30 23:59:59
  797. nowQuarterLastDay = time.Date(time.Now().Year(), 9, 30, 23, 59, 59, 0, time.Now().Location())
  798. } else {
  799. //12-31 23:59:59
  800. nowQuarterLastDay = time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
  801. }
  802. return nowQuarterLastDay
  803. }
  804. // GetNowHalfYearFirstDay 获取当前半年的第一天的时间
  805. func GetNowHalfYearFirstDay() time.Time {
  806. month := int(time.Now().Month())
  807. var nowHalfYearLastDay time.Time
  808. if month >= 1 && month <= 6 {
  809. //03-31 23:59:59
  810. nowHalfYearLastDay = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
  811. } else {
  812. //12-31 23:59:59
  813. nowHalfYearLastDay = time.Date(time.Now().Year(), 7, 1, 0, 0, 0, 0, time.Now().Location())
  814. }
  815. return nowHalfYearLastDay
  816. }
  817. // GetNowHalfYearLastDay 获取当前半年的最后一天的时间
  818. func GetNowHalfYearLastDay() time.Time {
  819. month := int(time.Now().Month())
  820. var nowHalfYearLastDay time.Time
  821. if month >= 1 && month <= 6 {
  822. //03-31 23:59:59
  823. nowHalfYearLastDay = time.Date(time.Now().Year(), 6, 30, 23, 59, 59, 0, time.Now().Location())
  824. } else {
  825. //12-31 23:59:59
  826. nowHalfYearLastDay = time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
  827. }
  828. return nowHalfYearLastDay
  829. }
  830. // GetNowYearFirstDay 获取当前年的最后一天的时间
  831. func GetNowYearFirstDay() time.Time {
  832. //12-31 23:59:59
  833. nowYearFirstDay := time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
  834. return nowYearFirstDay
  835. }
  836. // GetNowYearLastDay 获取当前年的最后一天的时间
  837. func GetNowYearLastDay() time.Time {
  838. //12-31 23:59:59
  839. nowYearLastDay := time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
  840. return nowYearLastDay
  841. }
  842. // CalculationDate 计算两个日期之间相差n年m月y天
  843. func CalculationDate(startDate, endDate time.Time) (beetweenDay string, err error) {
  844. //startDate := time.Date(2021, 3, 28, 0, 0, 0, 0, time.Now().Location())
  845. //endDate := time.Date(2022, 3, 31, 0, 0, 0, 0, time.Now().Location())
  846. numYear := endDate.Year() - startDate.Year()
  847. numMonth := int(endDate.Month()) - int(startDate.Month())
  848. numDay := 0
  849. //获取截止月的总天数
  850. endDateDays := getMonthDay(endDate.Year(), int(endDate.Month()))
  851. //获取截止月的前一个月
  852. endDatePrevMonthDate := endDate.AddDate(0, -1, 0)
  853. //获取截止日期的上一个月的总天数
  854. endDatePrevMonthDays := getMonthDay(endDatePrevMonthDate.Year(), int(endDatePrevMonthDate.Month()))
  855. //获取开始日期的的月份总天数
  856. startDateMonthDays := getMonthDay(startDate.Year(), int(startDate.Month()))
  857. //判断,截止月是否完全被选中,如果相等,那么代表截止月份全部天数被选择
  858. if endDate.Day() == endDateDays {
  859. numDay = startDateMonthDays - startDate.Day() + 1
  860. //如果剩余天数正好与开始日期的天数是一致的,那么月份加1
  861. if numDay == startDateMonthDays {
  862. numMonth++
  863. numDay = 0
  864. //超过月份了,那么年份加1
  865. if numMonth == 12 {
  866. numYear++
  867. numMonth = 0
  868. }
  869. }
  870. } else {
  871. numDay = endDate.Day() - startDate.Day() + 1
  872. }
  873. //天数小于0,那么向月份借一位
  874. if numDay < 0 {
  875. //向上一个月借一个月的天数
  876. numDay += endDatePrevMonthDays
  877. //总月份减去一个月
  878. numMonth = numMonth - 1
  879. }
  880. //月份小于0,那么向年份借一位
  881. if numMonth < 0 {
  882. //向上一个年借12个月
  883. numMonth += 12
  884. //总年份减去一年
  885. numYear = numYear - 1
  886. }
  887. if numYear < 0 {
  888. err = errors.New("日期异常")
  889. return
  890. }
  891. if numYear > 0 {
  892. beetweenDay += fmt.Sprint(numYear, "年")
  893. }
  894. if numMonth > 0 {
  895. beetweenDay += fmt.Sprint(numMonth, "个月")
  896. }
  897. if numDay > 0 {
  898. beetweenDay += fmt.Sprint(numDay, "天")
  899. }
  900. return
  901. }
  902. // FormatPrice 格式化展示金额数字(财务金额展示,小数点前,每三位用,隔开) 1,234,567,898.55
  903. func FormatPrice(price float64) (str string) {
  904. str = decimal.NewFromFloat(price).String()
  905. length := len(str)
  906. if length < 4 {
  907. return str
  908. }
  909. arr := strings.Split(str, ".") //用小数点符号分割字符串,为数组接收
  910. length1 := len(arr[0])
  911. if length1 < 4 {
  912. return str
  913. }
  914. count := (length1 - 1) / 3
  915. for i := 0; i < count; i++ {
  916. arr[0] = arr[0][:length1-(i+1)*3] + "," + arr[0][length1-(i+1)*3:]
  917. }
  918. return strings.Join(arr, ".") //将一系列字符串连接为一个字符串,之间用sep来分隔。
  919. }
  920. // getMonthDay 获取某年某月有多少天
  921. func getMonthDay(year, month int) (days int) {
  922. if month != 2 {
  923. if month == 4 || month == 6 || month == 9 || month == 11 {
  924. days = 30
  925. } else {
  926. days = 31
  927. }
  928. } else {
  929. if ((year%4) == 0 && (year%100) != 0) || (year%400) == 0 {
  930. days = 29
  931. } else {
  932. days = 28
  933. }
  934. }
  935. return
  936. }
  937. func SaveToFile(content, path string) error {
  938. f, err := os.Create(path)
  939. defer f.Close()
  940. if err != nil {
  941. return err
  942. }
  943. f.Write([]byte(content))
  944. return nil
  945. }
  946. // 用户参会时间转换
  947. func GetAttendanceDetailSeconds(secondNum int) string {
  948. var timeStr string
  949. if secondNum <= 60 {
  950. if secondNum < 10 {
  951. timeStr = "0" + strconv.Itoa(secondNum) + "''"
  952. } else {
  953. timeStr = strconv.Itoa(secondNum) + "''"
  954. }
  955. } else {
  956. var remainderStr string
  957. remainderNum := secondNum % 60
  958. minuteNum := secondNum / 60
  959. if remainderNum < 10 {
  960. remainderStr = "0" + strconv.Itoa(remainderNum) + "''"
  961. } else {
  962. remainderStr = strconv.Itoa(remainderNum) + "''"
  963. }
  964. if minuteNum < 10 {
  965. timeStr = "0" + strconv.Itoa(minuteNum) + "'" + remainderStr
  966. } else {
  967. timeStr = strconv.Itoa(minuteNum) + "'" + remainderStr
  968. }
  969. }
  970. return timeStr
  971. }
  972. // SubStr 截取字符串(中文)
  973. func SubStr(str string, subLen int) string {
  974. strRune := []rune(str)
  975. bodyRuneLen := len(strRune)
  976. if bodyRuneLen > subLen {
  977. bodyRuneLen = subLen
  978. }
  979. str = string(strRune[:bodyRuneLen])
  980. return str
  981. }
  982. // HideString 给字段加***(从字符串中间替换,少于需要替换的长度,那么就补全*的长度)
  983. // src 待*字符串
  984. // hideLen 需要加*的长度
  985. func HideString(src string, hideLen int) string {
  986. if src == "" {
  987. return src
  988. }
  989. str := []rune(src)
  990. if hideLen == 0 {
  991. hideLen = 4
  992. }
  993. hideStr := ""
  994. for i := 0; i < hideLen; i++ {
  995. hideStr += "*"
  996. }
  997. strLen := len(str)
  998. // 字符长度是1
  999. if strLen == 1 {
  1000. return string(str[:1]) + hideStr
  1001. }
  1002. //字符长度大于1,但是小于等于需要隐藏的字符长度,那么就隐藏中间,保留前后各一位字符
  1003. if strLen <= hideLen+2 {
  1004. return string(str[:1]) + hideStr + string(str[strLen-1:])
  1005. }
  1006. subLen := strLen - hideLen //剩余需要展示的字符长度
  1007. decimal.NewFromFloat(2)
  1008. frontLenDecimal := decimal.NewFromInt(int64(subLen)).Div(decimal.NewFromInt(2)) //前面需要展示的字符的长度
  1009. frontLen := frontLenDecimal.Floor().IntPart()
  1010. return string(str[:frontLen]) + hideStr + string(str[frontLen+int64(hideLen):])
  1011. }
  1012. func GetLocalIP() (ip string, err error) {
  1013. addrs, err := net.InterfaceAddrs()
  1014. if err != nil {
  1015. return
  1016. }
  1017. for _, addr := range addrs {
  1018. ipAddr, ok := addr.(*net.IPNet)
  1019. if !ok {
  1020. continue
  1021. }
  1022. if ipAddr.IP.IsLoopback() {
  1023. continue
  1024. }
  1025. if !ipAddr.IP.IsGlobalUnicast() {
  1026. continue
  1027. }
  1028. return ipAddr.IP.String(), nil
  1029. }
  1030. return
  1031. }
  1032. // GetNowWeekMonday 获取上一周周一的时间
  1033. func GetPreWeekMonday() time.Time {
  1034. nowMonday := GetNowWeekMonday()
  1035. return nowMonday.AddDate(0, 0, -7)
  1036. }
  1037. // GetNowWeekLastDay 获取上一周最后一天的时间
  1038. func GetPreWeekLastDay() time.Time {
  1039. nowSunday := GetNowWeekLastDay()
  1040. return nowSunday.AddDate(0, 0, -7)
  1041. }
  1042. // GetNextWeekMonday 获取下一周周一的时间
  1043. func GetNextWeekMonday() time.Time {
  1044. nowMonday := GetNowWeekMonday()
  1045. return nowMonday.AddDate(0, 0, 7)
  1046. }
  1047. // GetNextWeekLastDay 获取下一周最后一天的时间
  1048. func GetNextWeekLastDay() time.Time {
  1049. nowSunday := GetNowWeekLastDay()
  1050. return nowSunday.AddDate(0, 0, 7)
  1051. }
  1052. // 处理真实姓名,隐藏中间的部分,如:张*,张*将
  1053. func DealRealName(realName string) string {
  1054. if realName == "" {
  1055. return ""
  1056. }
  1057. names := bytes.Runes([]byte(realName))
  1058. fistName := names[0]
  1059. length := len(names)
  1060. if length == 2 {
  1061. return string(fistName) + "*"
  1062. } else if length > 2 {
  1063. lastName := names[length-1]
  1064. return string(fistName) + "*" + string(lastName)
  1065. }
  1066. return realName
  1067. }
  1068. // Implode php中的implode(用来将int型的切片转为string)
  1069. func Implode(idIntList []int) (str string) {
  1070. for _, id := range idIntList {
  1071. str += fmt.Sprint(id, ",")
  1072. }
  1073. str = str[:len(str)-1]
  1074. return
  1075. }
  1076. // InArrayByInt php中的in_array(判断Int类型的切片中是否存在该int值)
  1077. func InArrayByInt(idIntList []int, searchId int) (has bool) {
  1078. for _, id := range idIntList {
  1079. if id == searchId {
  1080. has = true
  1081. return
  1082. }
  1083. }
  1084. return
  1085. }
  1086. // InArrayByStr php中的in_array(判断String类型的切片中是否存在该string值)
  1087. func InArrayByStr(idStrList []string, searchId string) (has bool) {
  1088. for _, id := range idStrList {
  1089. if id == searchId {
  1090. has = true
  1091. return
  1092. }
  1093. }
  1094. return
  1095. }
  1096. // Intersection 求两个切片的交集
  1097. func Intersection(a []string, b []string) (inter []string) {
  1098. // interacting on the smallest list first can potentailly be faster...but not by much, worse case is the same
  1099. low, high := a, b
  1100. if len(a) > len(b) {
  1101. low = b
  1102. high = a
  1103. }
  1104. done := false
  1105. for i, l := range low {
  1106. for j, h := range high {
  1107. // get future index values
  1108. f1 := i + 1
  1109. f2 := j + 1
  1110. if l == h {
  1111. inter = append(inter, h)
  1112. if f1 < len(low) && f2 < len(high) {
  1113. // if the future values aren't the same then that's the end of the intersection
  1114. if low[f1] != high[f2] {
  1115. done = true
  1116. }
  1117. }
  1118. // we don't want to interate on the entire list everytime, so remove the parts we already looped on will make it faster each pass
  1119. high = high[:j+copy(high[j:], high[j+1:])]
  1120. break
  1121. }
  1122. }
  1123. // nothing in the future so we are done
  1124. if done {
  1125. break
  1126. }
  1127. }
  1128. return
  1129. }
  1130. // Minus 获取差集
  1131. func Minus(a []string, b []string) []string {
  1132. //var inter []string
  1133. inter := make([]string, 0)
  1134. mp := make(map[string]bool)
  1135. for _, s := range a {
  1136. if _, ok := mp[s]; !ok {
  1137. mp[s] = true
  1138. }
  1139. }
  1140. for _, s := range b {
  1141. if _, ok := mp[s]; ok {
  1142. delete(mp, s)
  1143. }
  1144. }
  1145. for key := range mp {
  1146. inter = append(inter, key)
  1147. }
  1148. return inter
  1149. }
  1150. // IntArr2joinString []int转字符串
  1151. func IntArr2joinString(arr []int, sep string) string {
  1152. if len(arr) == 0 {
  1153. return ""
  1154. }
  1155. strArr := make([]string, 0)
  1156. for _, v := range arr {
  1157. strArr = append(strArr, strconv.Itoa(v))
  1158. }
  1159. return strings.Join(strArr, sep)
  1160. }
  1161. // GetOneMonthFirstDay 获取某月的第一天的时间
  1162. func GetOneMonthFirstDay(time2 time.Time) time.Time {
  1163. nowMonthFirstDay := time.Date(time2.Year(), time2.Month(), 1, 0, 0, 0, 0, time.Now().Location())
  1164. return nowMonthFirstDay
  1165. }
  1166. // GetOneMonthLastDay 获取某月最后一天的时间
  1167. func GetOneMonthLastDay(time2 time.Time) time.Time {
  1168. nowMonthLastDay := time.Date(time2.Year(), time2.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  1169. nowMonthLastDay = time.Date(nowMonthLastDay.Year(), nowMonthLastDay.Month(), nowMonthLastDay.Day(), 23, 59, 59, 0, nowMonthLastDay.Location())
  1170. return nowMonthLastDay
  1171. }
  1172. func GetReportContentTextSub(content string) (contentSub string, err error) {
  1173. content = html.UnescapeString(content)
  1174. doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
  1175. docText := doc.Text()
  1176. bodyRune := []rune(docText)
  1177. bodyRuneLen := len(bodyRune)
  1178. if bodyRuneLen > 200 {
  1179. bodyRuneLen = 200
  1180. }
  1181. body := string(bodyRune[:bodyRuneLen])
  1182. contentSub = body
  1183. contentSub = strings.Replace(body, "Powered by Froala Editor", "", -1)
  1184. return
  1185. }
  1186. // GetOrmInReplace 获取orm的in查询替换?的方法
  1187. func GetOrmInReplace(num int) string {
  1188. template := make([]string, num)
  1189. for i := 0; i < num; i++ {
  1190. template[i] = "?"
  1191. }
  1192. return strings.Join(template, ",")
  1193. }
  1194. // RevSlice 反转切片
  1195. func RevSlice(slice []int) []int {
  1196. for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
  1197. slice[i], slice[j] = slice[j], slice[i]
  1198. }
  1199. return slice
  1200. }
  1201. // ReplaceSpaceAndWrap 去除空格跟换行
  1202. func ReplaceSpaceAndWrap(str string) string {
  1203. // 去除空格
  1204. str = strings.Replace(str, " ", "", -1)
  1205. // 去除换行符
  1206. str = strings.Replace(str, "\n", "", -1)
  1207. return str
  1208. }
  1209. // JoinStr2IntArr 拼接字符串转[]int
  1210. func JoinStr2IntArr(str, sep string) (arr []int) {
  1211. arr = make([]int, 0)
  1212. if str == "" {
  1213. return
  1214. }
  1215. if sep == "" {
  1216. sep = ","
  1217. }
  1218. strArr := strings.Split(str, sep)
  1219. if len(strArr) == 0 {
  1220. return
  1221. }
  1222. for i := range strArr {
  1223. v, e := strconv.Atoi(strArr[i])
  1224. // int2str此处过滤掉无效int
  1225. if e != nil {
  1226. continue
  1227. }
  1228. arr = append(arr, v)
  1229. }
  1230. return
  1231. }
  1232. // 字符串转换为time类型
  1233. func StrDateToDate(strTime string) time.Time {
  1234. timeLayout := "2006-01-02" //转化所需模板
  1235. loc, _ := time.LoadLocation("Local") //重要:获取时区
  1236. resultTime, _ := time.ParseInLocation(timeLayout, strTime, loc)
  1237. return resultTime
  1238. }
  1239. // GetTimeSubDay 计算两个时间的自然日期差(后面减去前面)
  1240. func GetTimeSubDay(t1, t2 time.Time) int {
  1241. var day int
  1242. swap := false
  1243. if t1.Unix() > t2.Unix() {
  1244. t1, t2 = t2, t1
  1245. swap = true
  1246. }
  1247. t1_ := t1.Add(time.Duration(t2.Sub(t1).Milliseconds()%86400000) * time.Millisecond)
  1248. day = int(t2.Sub(t1).Hours() / 24)
  1249. // 计算在t1+两个时间的余数之后天数是否有变化
  1250. if t1_.Day() != t1.Day() {
  1251. day += 1
  1252. }
  1253. if swap {
  1254. day = -day
  1255. }
  1256. return day
  1257. }
  1258. // 去除非中文字符串
  1259. func StrFilterNonChinese(src *string) {
  1260. var hzRegexp = regexp.MustCompile("^[\u4e00-\u9fa5]$")
  1261. strn := ""
  1262. for _, c := range *src {
  1263. if hzRegexp.MatchString(string(c)) {
  1264. strn += string(c)
  1265. }
  1266. }
  1267. *src = strn
  1268. }
  1269. // MinusInt 获取两个[]int差集
  1270. func MinusInt(a []int, b []int) []int {
  1271. var diff []int
  1272. mpA, mpB := make(map[int]bool), make(map[int]bool)
  1273. for _, v := range a {
  1274. mpA[v] = true
  1275. }
  1276. for _, v := range b {
  1277. mpB[v] = true
  1278. }
  1279. for _, s := range a {
  1280. if !mpB[s] {
  1281. diff = append(diff, s)
  1282. }
  1283. }
  1284. for _, s := range b {
  1285. if !mpA[s] {
  1286. diff = append(diff, s)
  1287. }
  1288. }
  1289. return diff
  1290. }
  1291. // IntersectInt 获取两个[]int交集
  1292. func IntersectInt(nums1 []int, nums2 []int) []int {
  1293. m := make(map[int]int)
  1294. var res []int
  1295. for _, num := range nums1 {
  1296. m[num]++
  1297. }
  1298. for _, num := range nums2 {
  1299. if m[num] > 0 {
  1300. res = append(res, num)
  1301. m[num]--
  1302. }
  1303. }
  1304. return res
  1305. }
  1306. // MapSorter 对于map 排序
  1307. type MapSorter []Item
  1308. type Item struct {
  1309. Key int
  1310. Val float64
  1311. }
  1312. func NewMapSorter(m map[int]float64) MapSorter {
  1313. ms := make(MapSorter, 0, len(m))
  1314. for k, v := range m {
  1315. ms = append(ms, Item{k, v})
  1316. }
  1317. return ms
  1318. }
  1319. func (ms MapSorter) Len() int {
  1320. return len(ms)
  1321. }
  1322. func (ms MapSorter) Less(i, j int) bool {
  1323. return ms[i].Val > ms[j].Val // 按值排序
  1324. //return ms[i].Key < ms[j].Key // 按键排序
  1325. }
  1326. func (ms MapSorter) Swap(i, j int) {
  1327. ms[i], ms[j] = ms[j], ms[i]
  1328. }
  1329. // FormatFileSize 字节的单位转换 保留两位小数
  1330. func FormatFileSize(fileSize int64) (size string) {
  1331. if fileSize < 1024 {
  1332. return fmt.Sprintf("%.2fB", float64(fileSize)/float64(1))
  1333. } else if fileSize < (1024 * 1024) {
  1334. return fmt.Sprintf("%.2fKB", float64(fileSize)/float64(1024))
  1335. } else if fileSize < (1024 * 1024 * 1024) {
  1336. return fmt.Sprintf("%.2fMB", float64(fileSize)/float64(1024*1024))
  1337. } else if fileSize < (1024 * 1024 * 1024 * 1024) {
  1338. return fmt.Sprintf("%.2fGB", float64(fileSize)/float64(1024*1024*1024))
  1339. } else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) {
  1340. return fmt.Sprintf("%.2fTB", float64(fileSize)/float64(1024*1024*1024*1024))
  1341. } else { //if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
  1342. return fmt.Sprintf("%.2fPB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
  1343. }
  1344. }
  1345. func GetDurationFormatBySecond(sec int) (formatString string) {
  1346. if sec == 0 {
  1347. formatString = "0分钟"
  1348. return
  1349. } else if sec <= 60 && sec > 0 {
  1350. formatString = "1分钟"
  1351. return
  1352. }
  1353. duration := time.Duration(int64(sec)) * time.Second
  1354. h := int(duration.Hours())
  1355. m := int(duration.Minutes()) % 60
  1356. //s := int(duration.Seconds()) % 60
  1357. if h > 0 {
  1358. formatString = fmt.Sprintf("%d小时", h)
  1359. }
  1360. if m > 0 {
  1361. formatString += fmt.Sprintf("%d分钟", m)
  1362. }
  1363. //if s > 0 {
  1364. // formatString += fmt.Sprintf("%d秒", s)
  1365. //}
  1366. return
  1367. }
  1368. // GetDaysBetween2Date 计算两个日期之间相差几天
  1369. func GetDaysBetween2Date(format, date1Str, date2Str string) (int, error) {
  1370. // 将字符串转化为Time格式
  1371. date1, err := time.ParseInLocation(format, date1Str, time.Local)
  1372. if err != nil {
  1373. return 0, err
  1374. }
  1375. // 将字符串转化为Time格式
  1376. date2, err := time.ParseInLocation(format, date2Str, time.Local)
  1377. if err != nil {
  1378. return 0, err
  1379. }
  1380. //计算相差天数
  1381. return int(date1.Sub(date2).Hours() / 24), nil
  1382. }
  1383. // GetFrequencyEn 获取频度的英文版
  1384. func GetFrequencyEn(frequency string) (frequencyEn string) {
  1385. switch frequency {
  1386. case "日度":
  1387. frequencyEn = "day"
  1388. return
  1389. case "周度":
  1390. frequencyEn = "week"
  1391. return
  1392. case "旬度":
  1393. frequencyEn = "ten days"
  1394. return
  1395. case "月度":
  1396. frequencyEn = "month"
  1397. return
  1398. case "季度":
  1399. frequencyEn = "quarter"
  1400. return
  1401. case "年度":
  1402. frequencyEn = "year"
  1403. return
  1404. }
  1405. return
  1406. }
  1407. // GetLeadUnitEn 获取移动单位的英文版
  1408. func GetLeadUnitEn(unit string) (unitEn string) {
  1409. switch unit {
  1410. case "天":
  1411. unitEn = "day"
  1412. return
  1413. case "周":
  1414. unitEn = "week"
  1415. return
  1416. case "月":
  1417. unitEn = "month"
  1418. return
  1419. case "季":
  1420. unitEn = "quarter"
  1421. return
  1422. case "年":
  1423. unitEn = "year"
  1424. return
  1425. }
  1426. return
  1427. }
  1428. // GetDateByDateType 通过dateType获取需要的开始/结束日期
  1429. func GetDateByDateType(dateType int, tmpStartDate, tmpEndDate string) (startDate, endDate string) {
  1430. startDate = tmpStartDate
  1431. endDate = tmpEndDate
  1432. switch dateType {
  1433. case 1:
  1434. startDate = "2000-01-01"
  1435. endDate = ""
  1436. case 2:
  1437. startDate = "2010-01-01"
  1438. endDate = ""
  1439. case 3:
  1440. startDate = "2015-01-01"
  1441. endDate = ""
  1442. case 4:
  1443. //startDate = strconv.Itoa(time.Now().Year()) + "-01-01"
  1444. startDate = "2021-01-01"
  1445. endDate = ""
  1446. case 5:
  1447. //startDate = startDate + "-01"
  1448. //endDate = endDate + "-01"
  1449. case 6:
  1450. //startDate = startDate + "-01"
  1451. endDate = ""
  1452. case 7:
  1453. startDate = "2018-01-01"
  1454. endDate = ""
  1455. case 8:
  1456. startDate = "2019-01-01"
  1457. endDate = ""
  1458. case 9:
  1459. startDate = "2020-01-01"
  1460. endDate = ""
  1461. case 11:
  1462. startDate = "2022-01-01"
  1463. endDate = ""
  1464. }
  1465. // 兼容日期错误
  1466. {
  1467. if strings.Count(startDate, "-") == 1 {
  1468. startDate = startDate + "-01"
  1469. }
  1470. if strings.Count(endDate, "-") == 1 {
  1471. endDate = endDate + "-01"
  1472. }
  1473. }
  1474. return
  1475. }
  1476. func TimeTransferString(format string, t time.Time) string {
  1477. str := t.Format(format)
  1478. if t.IsZero() {
  1479. return ""
  1480. }
  1481. return str
  1482. }
  1483. // GetDateByDateType2 通过dateType获取需要的开始/结束日期(日期类型:1:最近3月;2:最近6月;3:最近1年;4:最近2年;5:最近3年;6:最近5年;7:最近10年,8:自定义时间)
  1484. func GetDateByDateType2(dateType int, currDate time.Time) (startDate time.Time) {
  1485. switch dateType {
  1486. case 1:
  1487. startDate = currDate.AddDate(0, -3, 0)
  1488. case 2:
  1489. startDate = currDate.AddDate(0, -6, 0)
  1490. case 3:
  1491. startDate = currDate.AddDate(-1, 0, 0)
  1492. case 4:
  1493. startDate = currDate.AddDate(-2, 0, 0)
  1494. case 5:
  1495. startDate = currDate.AddDate(-3, 0, 0)
  1496. case 6:
  1497. startDate = currDate.AddDate(-5, 0, 0)
  1498. case 7:
  1499. startDate = currDate.AddDate(-10, 0, 0)
  1500. }
  1501. return
  1502. }
  1503. // GetCeilNewNum 保留n位有效数字的向上取整
  1504. // @params num 实际数据
  1505. // @params baseLen 需要保留的有效位数
  1506. func GetCeilNewNum(num float64, baseLen int) (newNum float64) {
  1507. if num >= 1 {
  1508. tmpNum := int(math.Ceil(num)) // 向上取整
  1509. str := strconv.Itoa(tmpNum)
  1510. lenStr := len(str)
  1511. if lenStr > baseLen {
  1512. newNumStr := str[0:baseLen]
  1513. newNumInt, _ := strconv.Atoi(newNumStr)
  1514. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1515. if newNum < num {
  1516. newNumInt += 1
  1517. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1518. }
  1519. } else {
  1520. newNum = float64(tmpNum)
  1521. }
  1522. return
  1523. } else if num > 0 {
  1524. // 这是小数
  1525. str := strconv.FormatFloat(num, 'f', -1, 64)
  1526. // 去除小数点和负号
  1527. str = removeDecimalPoint(str)
  1528. // 计算字符串长度
  1529. lenStr := len(str)
  1530. if lenStr > baseLen {
  1531. newNumStr := str[0:baseLen]
  1532. newNumInt, _ := strconv.Atoi(newNumStr)
  1533. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1534. if newNum < num {
  1535. newNumInt += 1
  1536. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1537. }
  1538. } else {
  1539. newNum = num
  1540. }
  1541. } else if num > -1 {
  1542. // 这是小数
  1543. str := strconv.FormatFloat(num, 'f', -1, 64)
  1544. // 去除小数点和负号
  1545. str = removeDecimalPoint(str)
  1546. // 计算字符串长度
  1547. lenStr := len(str)
  1548. if lenStr > baseLen {
  1549. newNumStr := str[0:baseLen]
  1550. newNumInt, _ := strconv.Atoi(newNumStr)
  1551. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1552. newNum = -newNum
  1553. if newNum < num {
  1554. newNumInt -= 1
  1555. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1556. newNum = -newNum
  1557. }
  1558. } else {
  1559. newNum = num
  1560. }
  1561. if newNum == -0 {
  1562. newNum = 0
  1563. }
  1564. } else { // 小于等于-1
  1565. tmpNumFloat := math.Abs(num)
  1566. tmpNum := int(math.Floor(tmpNumFloat)) // 向上取整
  1567. str := strconv.Itoa(tmpNum)
  1568. lenStr := len(str)
  1569. if lenStr > baseLen {
  1570. newNumStr := str[0:baseLen]
  1571. //fmt.Println("newNumStr:", newNumStr)
  1572. newNumInt, _ := strconv.Atoi(newNumStr)
  1573. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1574. newNum = -newNum
  1575. if newNum < num {
  1576. newNumInt -= 1
  1577. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1578. newNum = -newNum
  1579. }
  1580. } else {
  1581. newNum = float64(-tmpNum)
  1582. }
  1583. }
  1584. return
  1585. }
  1586. // GetFloorNewNum 保留n位有效数字的向下取整
  1587. // @params num 实际数据
  1588. // @params baseLen 需要保留的有效位数
  1589. func GetFloorNewNum(num float64, baseLen int) (newNum float64) {
  1590. if num >= 1 {
  1591. tmpNum := int(math.Floor(num)) // 向上取整
  1592. str := strconv.Itoa(tmpNum)
  1593. lenStr := len(str)
  1594. if lenStr > baseLen {
  1595. newNumStr := str[0:baseLen]
  1596. newNumInt, _ := strconv.Atoi(newNumStr)
  1597. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1598. if newNum < num {
  1599. newNumInt -= 1
  1600. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1601. }
  1602. } else {
  1603. newNum = float64(tmpNum)
  1604. }
  1605. return
  1606. } else if num > 0 {
  1607. // 这是小数
  1608. str := strconv.FormatFloat(num, 'f', -1, 64)
  1609. // 去除小数点和负号
  1610. str = removeDecimalPoint(str)
  1611. // 计算字符串长度
  1612. lenStr := len(str)
  1613. if lenStr > baseLen {
  1614. newNumStr := str[0:baseLen]
  1615. newNumInt, _ := strconv.Atoi(newNumStr)
  1616. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1617. if newNum > num {
  1618. newNumInt -= 1
  1619. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1620. }
  1621. } else {
  1622. newNum = num
  1623. }
  1624. } else if num > -1 {
  1625. // 这是小数
  1626. str := strconv.FormatFloat(num, 'f', -1, 64)
  1627. // 去除小数点和负号
  1628. str = removeDecimalPoint(str)
  1629. // 计算字符串长度
  1630. lenStr := len(str)
  1631. if lenStr > baseLen {
  1632. newNumStr := str[0:baseLen]
  1633. newNumInt, _ := strconv.Atoi(newNumStr)
  1634. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1635. newNum = -newNum
  1636. if newNum > num {
  1637. newNumInt += 1
  1638. newNum, _ = decimal.NewFromInt(int64(newNumInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(baseLen)))).Float64()
  1639. newNum = -newNum
  1640. }
  1641. } else {
  1642. newNum = num
  1643. }
  1644. if newNum == -0 {
  1645. newNum = 0
  1646. }
  1647. } else { // 小于等于-1
  1648. tmpNumFloat := math.Abs(num)
  1649. tmpNum := int(math.Ceil(tmpNumFloat)) // 向上取整
  1650. str := strconv.Itoa(tmpNum)
  1651. lenStr := len(str)
  1652. if lenStr > baseLen {
  1653. newNumStr := str[0:baseLen]
  1654. //fmt.Println("newNumStr:", newNumStr)
  1655. newNumInt, _ := strconv.Atoi(newNumStr)
  1656. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1657. newNum = -newNum
  1658. if newNum > num {
  1659. newNumInt += 1
  1660. newNum = float64(newNumInt) * math.Pow(10, float64(lenStr-baseLen))
  1661. newNum = -newNum
  1662. }
  1663. } else {
  1664. newNum = float64(-tmpNum)
  1665. }
  1666. }
  1667. return
  1668. }
  1669. // 去除小数点和负号
  1670. func removeDecimalPoint(str string) string {
  1671. // 去除小数点
  1672. str = str[strings.Index(str, ".")+1:]
  1673. return str
  1674. }
  1675. // GetPredictEdbDayListByEndDate 根据截止日期获取预测指标日期列表
  1676. func GetPredictEdbDayListByEndDate(startDate, endDate time.Time, frequency string) (dayList []time.Time) {
  1677. //if !utils.InArrayByStr([]string{"日度", "周度", "月度"}, frequency)
  1678. switch frequency {
  1679. case "日度":
  1680. for currDate := startDate.AddDate(0, 0, 1); currDate.Before(endDate) || currDate.Equal(endDate); currDate = currDate.AddDate(0, 0, 1) {
  1681. //周六、日排除
  1682. if currDate.Weekday() == time.Sunday || currDate.Weekday() == time.Saturday {
  1683. continue
  1684. }
  1685. dayList = append(dayList, currDate)
  1686. }
  1687. case "周度":
  1688. //nextDate := startDate.AddDate(0, 0, 7)
  1689. for currDate := startDate.AddDate(0, 0, 7); currDate.Before(endDate) || currDate.Equal(endDate); currDate = currDate.AddDate(0, 0, 7) {
  1690. dayList = append(dayList, currDate)
  1691. }
  1692. case "旬度":
  1693. for currDate := startDate.AddDate(0, 0, 1); currDate.Before(endDate) || currDate.Equal(endDate); {
  1694. nextDate := currDate.AddDate(0, 0, 1)
  1695. //每个月的10号、20号、最后一天,那么就写入
  1696. if nextDate.Day() == 11 || nextDate.Day() == 21 || nextDate.Day() == 1 {
  1697. dayList = append(dayList, currDate)
  1698. }
  1699. currDate = nextDate
  1700. }
  1701. case "月度":
  1702. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  1703. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  1704. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  1705. dayList = append(dayList, currDate)
  1706. }
  1707. currDate = currDate.AddDate(0, 0, 1)
  1708. }
  1709. case "季度":
  1710. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  1711. // 每月的最后一天
  1712. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  1713. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  1714. // 季度日期就写入,否则不写入
  1715. if currDate.Month() == 3 || currDate.Month() == 6 || currDate.Month() == 9 || currDate.Month() == 12 {
  1716. dayList = append(dayList, currDate)
  1717. }
  1718. }
  1719. currDate = currDate.AddDate(0, 0, 1)
  1720. }
  1721. case "半年度":
  1722. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  1723. // 每月的最后一天
  1724. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  1725. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  1726. // 半年度日期就写入,否则不写入
  1727. if currDate.Month() == 6 || currDate.Month() == 12 {
  1728. dayList = append(dayList, currDate)
  1729. }
  1730. }
  1731. currDate = currDate.AddDate(0, 0, 1)
  1732. }
  1733. case "年度":
  1734. for currDate := startDate; currDate.Before(endDate) || currDate.Equal(endDate); {
  1735. currDate = time.Date(currDate.Year()+1, 12, 31, 0, 0, 0, 0, time.Now().Location())
  1736. if !currDate.After(endDate) && !currDate.Equal(startDate) {
  1737. dayList = append(dayList, currDate)
  1738. }
  1739. }
  1740. }
  1741. return
  1742. }
  1743. // GetPredictEdbDayListByNum 根据期数获取预测指标日期列表
  1744. func GetPredictEdbDayListByNum(startDate time.Time, num int, frequency string) (dayList []time.Time) {
  1745. switch frequency {
  1746. case "日度":
  1747. for i := 1; i <= num; {
  1748. currDate := startDate.AddDate(0, 0, i)
  1749. //周六、日排除
  1750. if currDate.Weekday() == time.Sunday || currDate.Weekday() == time.Saturday {
  1751. continue
  1752. }
  1753. dayList = append(dayList, currDate)
  1754. i++
  1755. }
  1756. case "周度":
  1757. for i := 1; i <= num; {
  1758. dayList = append(dayList, startDate.AddDate(0, 0, i*7))
  1759. i++
  1760. }
  1761. case "旬度":
  1762. currDate := startDate
  1763. for i := 1; i <= num; {
  1764. nextDate := currDate.AddDate(0, 0, 1)
  1765. //每个月的10号、20号、最后一天,那么就写入
  1766. if nextDate.Day() == 11 || nextDate.Day() == 21 || nextDate.Day() == 1 {
  1767. dayList = append(dayList, currDate)
  1768. i++
  1769. }
  1770. currDate = nextDate
  1771. }
  1772. case "月度":
  1773. currDate := startDate
  1774. for i := 1; i <= num; {
  1775. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  1776. if !currDate.Equal(startDate) {
  1777. dayList = append(dayList, currDate)
  1778. i++
  1779. }
  1780. currDate = currDate.AddDate(0, 0, 1)
  1781. }
  1782. case "季度":
  1783. currDate := startDate
  1784. for i := 1; i <= num; {
  1785. // 每月的最后一天
  1786. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  1787. if !currDate.Equal(startDate) {
  1788. // 季度日期就写入,否则不写入
  1789. if currDate.Month() == 3 || currDate.Month() == 6 || currDate.Month() == 9 || currDate.Month() == 12 {
  1790. dayList = append(dayList, currDate)
  1791. i++
  1792. }
  1793. }
  1794. currDate = currDate.AddDate(0, 0, 1)
  1795. }
  1796. case "半年度":
  1797. currDate := startDate
  1798. for i := 1; i <= num; {
  1799. // 每月的最后一天
  1800. currDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  1801. if !currDate.Equal(startDate) {
  1802. // 半年度日期就写入,否则不写入
  1803. if currDate.Month() == 6 || currDate.Month() == 12 {
  1804. dayList = append(dayList, currDate)
  1805. i++
  1806. }
  1807. }
  1808. currDate = currDate.AddDate(0, 0, 1)
  1809. }
  1810. case "年度":
  1811. currDate := startDate
  1812. for i := 1; i <= num; {
  1813. currDate = time.Date(currDate.Year()+1, 12, 31, 0, 0, 0, 0, time.Now().Location())
  1814. if !currDate.Equal(startDate) {
  1815. dayList = append(dayList, currDate)
  1816. i++
  1817. }
  1818. }
  1819. }
  1820. return
  1821. }
  1822. func GetDateByDateTypeV2(dateType int, tmpStartDate, tmpEndDate string, startYear, yearMax int) (startDate, endDate string) {
  1823. startDate = tmpStartDate
  1824. endDate = tmpEndDate
  1825. switch dateType {
  1826. case 1:
  1827. startDate = "2000-01-01"
  1828. endDate = ""
  1829. case 2:
  1830. startDate = "2010-01-01"
  1831. endDate = ""
  1832. case 3:
  1833. startDate = "2015-01-01"
  1834. endDate = ""
  1835. case 4:
  1836. //startDate = strconv.Itoa(time.Now().Year()) + "-01-01"
  1837. startDate = "2021-01-01"
  1838. endDate = ""
  1839. case 5:
  1840. //startDate = startDate + "-01"
  1841. //endDate = endDate + "-01"
  1842. case 6:
  1843. //startDate = startDate + "-01"
  1844. endDate = ""
  1845. case 7:
  1846. startDate = "2018-01-01"
  1847. endDate = ""
  1848. case 8:
  1849. startDate = "2019-01-01"
  1850. endDate = ""
  1851. case 9:
  1852. startDate = "2020-01-01"
  1853. endDate = ""
  1854. case 11:
  1855. startDate = "2022-01-01"
  1856. endDate = ""
  1857. case DateTypeNYears:
  1858. if startYear == 0 { //默认取最近5年
  1859. startYear = 5
  1860. }
  1861. if yearMax == 0 {
  1862. return
  1863. }
  1864. startYear = startYear - 1
  1865. baseDate, _ := time.Parse(FormatDate, fmt.Sprintf("%d-01-01", yearMax))
  1866. startDate = baseDate.AddDate(-startYear, 0, 0).Format(FormatDate)
  1867. endDate = ""
  1868. }
  1869. // 兼容日期错误
  1870. {
  1871. if strings.Count(startDate, "-") == 1 {
  1872. startDate = startDate + "-01"
  1873. }
  1874. if strings.Count(endDate, "-") == 1 {
  1875. endDate = endDate + "-01"
  1876. }
  1877. }
  1878. return
  1879. }
  1880. // ArrContainsStr 函数检查一个字符串是否在字符串数组中
  1881. func ArrContainsStr(arr []string, str string) bool {
  1882. for _, v := range arr {
  1883. if v == str {
  1884. return true
  1885. }
  1886. }
  1887. return false
  1888. }
  1889. func GetColorMap() map[int]string {
  1890. colorMap := make(map[int]string)
  1891. colors := []string{"#0000FF", "#FF0000", "#999999", "#000000", "#7CB5EC", "#90ED7D", "#F7A35C", "#8085E9",
  1892. "#F15C80", "#E4D354", "#2B908F", "#F45B5B", "#91E8E1", "#FDA8C7", "#8A4294",
  1893. "#578B5A", "#0033FF", "#849EC1", "#FFDF0C", "#005496", "#00F0FF", "#4D535B",
  1894. "#4F4C34", "#804141", "#86BABD", "#8AA3FF", "#960000", "#A173DB", "#A39340",
  1895. "#CE814A", "#D1D2E6", "#EAB7B7", "#FF2E7A", "#FF4AF8", "#FF785B", "#FF9696", "#FFA800", "#FFBC97", "#FFDFDF"}
  1896. for k, v := range colors {
  1897. colorMap[k] = v
  1898. }
  1899. return colorMap
  1900. }
  1901. // IsPercentage
  1902. // @Description: 判断一个字符串是否是百分比的字符串,并返回百分比的值(比如:50%,返回true 50)
  1903. // @author: Roc
  1904. // @datetime 2023-11-29 14:00:31
  1905. // @param input string
  1906. // @return bool
  1907. // @return string
  1908. func IsPercentage(input string) (bool, string) {
  1909. percentagePattern := `^-?(\d+(\.\d+)?)%$`
  1910. match, _ := regexp.MatchString(percentagePattern, input)
  1911. if match {
  1912. re := regexp.MustCompile(percentagePattern)
  1913. match := re.FindStringSubmatch(input)
  1914. // 区分负数和正数,确保返回结果包含负号(如有)
  1915. sign := "-"
  1916. if input[0] != '-' {
  1917. sign = ""
  1918. }
  1919. return true, sign + match[1]
  1920. }
  1921. return false, ""
  1922. }
  1923. // GetLikeKeyword
  1924. //
  1925. // @Description: 获取sql查询中的like查询字段
  1926. // @author: Roc
  1927. // @datetime2023-10-23 14:46:32
  1928. // @param keyword string
  1929. // @return string
  1930. func GetLikeKeyword(keyword string) string {
  1931. return `%` + keyword + `%`
  1932. }
  1933. // GetLikeKeywordPars
  1934. //
  1935. // @Description: 获取sql查询中的参数切片
  1936. // @author: Roc
  1937. // @datetime2023-10-23 14:50:18
  1938. // @param pars []interface{}
  1939. // @param keyword string
  1940. // @param num int
  1941. // @return newPars []interface{}
  1942. func GetLikeKeywordPars(pars []interface{}, keyword string, num int) (newPars []interface{}) {
  1943. newPars = pars
  1944. if newPars == nil {
  1945. newPars = make([]interface{}, 0)
  1946. }
  1947. for i := 1; i <= num; i++ {
  1948. newPars = append(newPars, `%`+keyword+`%`)
  1949. }
  1950. return
  1951. }
  1952. // FormatMixTableDataShowValue 格式化自定表格显示数据
  1953. func FormatMixTableDataShowValue(x float64) (res string) {
  1954. res = fmt.Sprint(x)
  1955. return
  1956. }
  1957. // FormatTableDataShowValue 格式化自定表格显示数据
  1958. func FormatTableDataShowValue(x float64) (res string) {
  1959. if x > 1 || x < -1 {
  1960. res = decimal.NewFromFloat(x).Round(2).String()
  1961. return
  1962. }
  1963. // 介于-1到1之间
  1964. xStr := strconv.FormatFloat(x, 'f', -10, 64)
  1965. // 使用 strings.Split 函数将小数拆分为整数部分和小数部分
  1966. xParts := strings.Split(xStr, ".")
  1967. if len(xParts) < 2 {
  1968. res = fmt.Sprint(x)
  1969. return
  1970. }
  1971. // 计算小数部分的长度,即小数点后面的位数
  1972. xDecimals := len(xParts[1])
  1973. if xDecimals > 2 {
  1974. parts := xParts[1]
  1975. // 小数点后小于等于两位, 直接拼接返回
  1976. partLen := len(xParts[1])
  1977. if partLen <= 2 {
  1978. res = xParts[0] + "." + parts
  1979. return
  1980. }
  1981. // 找出第一个有效数字, 算出n
  1982. one := 0
  1983. for k, p := range parts {
  1984. // 48->0
  1985. if p != 48 {
  1986. if one == 0 {
  1987. one = k + 1
  1988. }
  1989. }
  1990. }
  1991. n := partLen - one
  1992. if n >= 1 {
  1993. n -= 1
  1994. } else {
  1995. one -= 1
  1996. }
  1997. var partFloat float64
  1998. partInt, _ := strconv.Atoi(parts)
  1999. partFloat, _ = decimal.NewFromInt(int64(partInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(n)))).Float64()
  2000. partFloat = math.Round(partFloat)
  2001. partFloat, _ = decimal.NewFromFloat(partFloat).Div(decimal.NewFromFloat(math.Pow(10, float64(one+1)))).Float64()
  2002. resParts := strings.Split(fmt.Sprint(partFloat), ".")
  2003. resPart := ""
  2004. if len(resParts) > 1 {
  2005. resPart = resParts[1]
  2006. } else {
  2007. resPart = resParts[0]
  2008. }
  2009. res = xParts[0] + "." + resPart
  2010. }
  2011. if xDecimals <= 2 {
  2012. xDecimalsStr := xParts[1]
  2013. x, _ = strconv.ParseFloat(xParts[0]+"."+xDecimalsStr, 64)
  2014. res = xParts[0] + "." + xDecimalsStr
  2015. }
  2016. return
  2017. }
  2018. func DealDateTimeZero(t time.Time, format string) (timeStr string) {
  2019. if !t.IsZero() {
  2020. timeStr = t.Format(format)
  2021. }
  2022. return
  2023. }
  2024. // SecondsToHHMMSS 秒转HH:MM:SS
  2025. func SecondsToHHMMSS(seconds int) string {
  2026. duration := time.Duration(seconds) * time.Second
  2027. hours := int(duration.Hours())
  2028. minutes := int(duration.Minutes()) % 60
  2029. seconds = int(duration.Seconds()) % 60
  2030. if hours > 0 {
  2031. return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
  2032. } else {
  2033. return fmt.Sprintf("%02d:%02d", minutes, seconds)
  2034. }
  2035. }
  2036. // MillisecondsToHHMMSS 毫秒转HH:MM:SS
  2037. func MillisecondsToHHMMSS(ms int) string {
  2038. duration := time.Duration(ms) * time.Millisecond
  2039. hours := int(duration / (time.Hour))
  2040. minutes := int((duration % (time.Hour)) / time.Minute)
  2041. seconds := int((duration % time.Hour % time.Minute) / time.Second)
  2042. // 将整数小时、分钟和秒数转换为字符串,并添加冒号分隔符
  2043. hourStr := strconv.Itoa(hours)
  2044. minuteStr := strconv.Itoa(minutes)
  2045. secondStr := strconv.Itoa(seconds)
  2046. // 根据不足两位数的情况补零
  2047. if len(hourStr) == 1 {
  2048. hourStr = "0" + hourStr
  2049. }
  2050. if len(minuteStr) == 1 {
  2051. minuteStr = "0" + minuteStr
  2052. }
  2053. if len(secondStr) == 1 {
  2054. secondStr = "0" + secondStr
  2055. }
  2056. return hourStr + ":" + minuteStr + ":" + secondStr
  2057. }
  2058. func ByteToMB(byteCount int) float64 {
  2059. return float64(byteCount) / (1024 * 1024)
  2060. }
  2061. // DateConvMysqlConvMongo
  2062. // @Description: 将mysql中的日期比较符转换成mongo中的日期比较符
  2063. // @author: Roc
  2064. // @datetime 2024-05-08 11:03:26
  2065. // @param dateCon string
  2066. func DateConvMysqlConvMongo(dateCon string) string {
  2067. cond := ""
  2068. switch dateCon {
  2069. case "=":
  2070. cond = "$eq"
  2071. case "<":
  2072. cond = "$lt"
  2073. case "<=":
  2074. cond = "$lte"
  2075. case ">":
  2076. cond = "$gt"
  2077. case ">=":
  2078. cond = "$gte"
  2079. }
  2080. return cond
  2081. }
  2082. // handleSystemAppointDateT
  2083. // @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  2084. // @author: Roc
  2085. // @datetime2023-10-27 09:31:35
  2086. // @param Frequency string
  2087. // @param Day string
  2088. // @return date string
  2089. // @return err error
  2090. // @return errMsg string
  2091. func HandleSystemAppointDateT(currDate time.Time, appointDay, frequency string) (date string, err error, errMsg string) {
  2092. //currDate := time.Now()
  2093. switch frequency {
  2094. case "本周":
  2095. day := int(currDate.Weekday())
  2096. if day == 0 { // 周日
  2097. day = 7
  2098. }
  2099. num := 0
  2100. switch appointDay {
  2101. case "周一":
  2102. num = 1
  2103. case "周二":
  2104. num = 2
  2105. case "周三":
  2106. num = 3
  2107. case "周四":
  2108. num = 4
  2109. case "周五":
  2110. num = 5
  2111. case "周六":
  2112. num = 6
  2113. case "周日":
  2114. num = 7
  2115. }
  2116. day = num - day
  2117. date = currDate.AddDate(0, 0, day).Format(FormatDate)
  2118. case "本旬":
  2119. day := currDate.Day()
  2120. var tmpDate time.Time
  2121. switch appointDay {
  2122. case "第一天":
  2123. if day <= 10 {
  2124. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  2125. } else if day <= 20 {
  2126. tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
  2127. } else {
  2128. tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
  2129. }
  2130. case "最后一天":
  2131. if day <= 10 {
  2132. tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
  2133. } else if day <= 20 {
  2134. tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
  2135. } else {
  2136. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  2137. }
  2138. }
  2139. date = tmpDate.Format(FormatDate)
  2140. case "本月":
  2141. var tmpDate time.Time
  2142. switch appointDay {
  2143. case "第一天":
  2144. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  2145. case "最后一天":
  2146. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  2147. }
  2148. date = tmpDate.Format(FormatDate)
  2149. case "本季":
  2150. month := currDate.Month()
  2151. var tmpDate time.Time
  2152. switch appointDay {
  2153. case "第一天":
  2154. if month <= 3 {
  2155. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  2156. } else if month <= 6 {
  2157. tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
  2158. } else if month <= 9 {
  2159. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  2160. } else {
  2161. tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
  2162. }
  2163. case "最后一天":
  2164. if month <= 3 {
  2165. tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
  2166. } else if month <= 6 {
  2167. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  2168. } else if month <= 9 {
  2169. tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
  2170. } else {
  2171. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  2172. }
  2173. }
  2174. date = tmpDate.Format(FormatDate)
  2175. case "本半年":
  2176. month := currDate.Month()
  2177. var tmpDate time.Time
  2178. switch appointDay {
  2179. case "第一天":
  2180. if month <= 6 {
  2181. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  2182. } else {
  2183. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  2184. }
  2185. case "最后一天":
  2186. if month <= 6 {
  2187. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  2188. } else {
  2189. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  2190. }
  2191. }
  2192. date = tmpDate.Format(FormatDate)
  2193. case "本年":
  2194. var tmpDate time.Time
  2195. switch appointDay {
  2196. case "第一天":
  2197. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  2198. case "最后一天":
  2199. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  2200. }
  2201. date = tmpDate.Format(FormatDate)
  2202. default:
  2203. errMsg = "错误的日期频度:" + frequency
  2204. err = errors.New(errMsg)
  2205. return
  2206. }
  2207. return
  2208. }
  2209. func CompareFloatByOpStrings(op string, a, b float64) bool {
  2210. switch op {
  2211. case "=":
  2212. return a == b
  2213. case ">":
  2214. return a > b
  2215. case ">=":
  2216. return a >= b
  2217. case "<=":
  2218. return a <= b
  2219. case "<":
  2220. return a < b
  2221. }
  2222. return false
  2223. }
  2224. // 检查src属性是否以http或data:image开头
  2225. func isValidSrc(src string) bool {
  2226. // 使用Parse函数解析URL
  2227. parsedURL, err := url.Parse(src)
  2228. if err != nil {
  2229. validSchemes := regexp.MustCompile(`^data:image\/.*;base64,.*$`)
  2230. return validSchemes.MatchString(src)
  2231. }
  2232. if parsedURL.Host == "" || (parsedURL.Scheme != "http" && parsedURL.Scheme != "https") {
  2233. validSchemes := regexp.MustCompile(`^data:image\/.*;base64,.*$`)
  2234. return validSchemes.MatchString(src)
  2235. }
  2236. return true
  2237. }
  2238. // ContentXssCheck 校验文本中的JS代码
  2239. func ContentXssCheck(content string) (err error) {
  2240. // 解析HTML内容
  2241. node, err := xhtml.Parse(strings.NewReader(content))
  2242. if err != nil {
  2243. err = fmt.Errorf(" html.Parse Err: %v", err)
  2244. return
  2245. }
  2246. // 遍历解析后的节点树,查找特定标签
  2247. var visit func(n *xhtml.Node) error
  2248. visit = func(n *xhtml.Node) error {
  2249. if n.Type == xhtml.ElementNode {
  2250. lowerData := strings.ToLower(n.Data)
  2251. switch lowerData {
  2252. case "script", "javascript":
  2253. err = fmt.Errorf(" script is forbidden")
  2254. return err
  2255. default:
  2256. for _, attr := range n.Attr { //判断事件
  2257. lowerKey := strings.ToLower(attr.Key)
  2258. lowerVal := strings.ToLower(attr.Val)
  2259. if lowerKey == "src" || lowerKey == "dynsrc" || lowerKey == "background" || lowerKey == "lowsrc" {
  2260. if lowerVal != `` && !isValidSrc(lowerVal) {
  2261. err = fmt.Errorf("invalid src attribute value: %s", attr.Val)
  2262. return err
  2263. }
  2264. }
  2265. if strings.HasPrefix(lowerKey, "on") {
  2266. err = fmt.Errorf("the event is forbidden: %s:%s", attr.Key, attr.Val)
  2267. return err
  2268. }
  2269. if lowerKey == "style" {
  2270. if strings.Contains(lowerVal, "javascript:") || strings.Contains(lowerVal, "script:") {
  2271. err = fmt.Errorf("invalid style attribute value: %s", attr.Val)
  2272. return err
  2273. }
  2274. }
  2275. }
  2276. /* case "src":
  2277. // 如果<src>是某个标签的属性,你可能需要递归检查其父节点
  2278. // 这里简单起见,我们假设<src>不是有效的HTML标签,并忽略它
  2279. // 在实际中,你可能需要更复杂的逻辑来处理这种情况
  2280. fmt.Println("Warning: Unexpected 'src' tag found.")*/
  2281. }
  2282. }
  2283. for c := n.FirstChild; c != nil; c = c.NextSibling {
  2284. if err = visit(c); err != nil {
  2285. return err
  2286. }
  2287. }
  2288. return nil
  2289. }
  2290. // 检查HTML文档中的事件
  2291. if err = visit(node); err != nil {
  2292. return
  2293. }
  2294. return
  2295. }
  2296. func ContentXssFilter(content string) (cleanContent string) {
  2297. p := customXssPolicy()
  2298. // The policy can then be used to sanitize lots of input and it is safe to use the policy in multiple goroutines
  2299. cleanContent = p.Sanitize(
  2300. content,
  2301. )
  2302. return
  2303. }
  2304. func customXssPolicy() (p *bluemonday.Policy) {
  2305. p = bluemonday.UGCPolicy()
  2306. // iframe
  2307. p.AllowElements("iframe")
  2308. p.AllowAttrs("width").OnElements("iframe")
  2309. p.AllowAttrs("height").OnElements("iframe")
  2310. p.AllowAttrs("src").OnElements("iframe")
  2311. p.AllowAttrs("frameborder").Matching(bluemonday.Number).OnElements("iframe")
  2312. p.AllowAttrs("allow").Matching(regexp.MustCompile(`[a-z; -]*`)).OnElements("iframe")
  2313. p.AllowAttrs("allowfullscreen").OnElements("iframe")
  2314. return
  2315. }
  2316. // GetCurrentTime 获取当前时间 格式为 2024-08-07 15:29:58
  2317. func GetCurrentTime() string {
  2318. return time.Now().Format("2006-01-02 15:04:05")
  2319. }
  2320. // MurmurHash64 计算字符串的64位哈希值
  2321. func MurmurHash64(val []byte) uint64 {
  2322. hash64 := murmur3.New64()
  2323. hash64.Write(val)
  2324. return hash64.Sum64()
  2325. }
  2326. const base62Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  2327. type TUint interface {
  2328. uint64 | uint32 | uint16 | uint8 | uint
  2329. }
  2330. // ConvertNumToBase62 转换数字为base62编码
  2331. func ConvertNumToBase62[T TUint](num T) string {
  2332. if num == 0 {
  2333. return string(base62Chars[0])
  2334. }
  2335. var result []byte
  2336. for num > 0 {
  2337. remainder := num % 62
  2338. result = append(result, base62Chars[remainder])
  2339. num /= 62
  2340. }
  2341. // 反转结果
  2342. for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
  2343. result[i], result[j] = result[j], result[i]
  2344. }
  2345. return string(result)
  2346. }