common.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  1. package utils
  2. import (
  3. "bufio"
  4. "crypto/md5"
  5. "crypto/sha1"
  6. "encoding/base64"
  7. "encoding/hex"
  8. "encoding/json"
  9. "errors"
  10. "fmt"
  11. "github.com/mozillazg/go-pinyin"
  12. "github.com/shopspring/decimal"
  13. "image"
  14. "image/png"
  15. "io"
  16. "math"
  17. "math/rand"
  18. "net"
  19. "net/http"
  20. "os"
  21. "os/exec"
  22. "path"
  23. "regexp"
  24. "runtime"
  25. "strconv"
  26. "strings"
  27. "time"
  28. )
  29. // GetFirstPingYin 拼音首字母
  30. func GetFirstPingYin(name string) string {
  31. a := pinyin.NewArgs()
  32. a.Separator = ""
  33. a.Style = pinyin.FirstLetter
  34. a.Fallback = func(r rune, a pinyin.Args) []string {
  35. return []string{string(r)}
  36. }
  37. rows := pinyin.Pinyin(name, a)
  38. code := ""
  39. for _, item := range rows {
  40. for _, v := range item {
  41. code += v
  42. }
  43. }
  44. return code
  45. }
  46. // GetFullPingYin 获取全拼音
  47. func GetFullPingYin(name string) string {
  48. a := pinyin.NewArgs()
  49. a.Separator = ""
  50. a.Style = pinyin.Normal
  51. a.Fallback = func(r rune, a pinyin.Args) []string {
  52. return []string{string(r)}
  53. }
  54. rows := pinyin.Pinyin(name, a)
  55. code := ""
  56. for _, item := range rows {
  57. for _, v := range item {
  58. code += v
  59. }
  60. }
  61. return code
  62. }
  63. // 随机数种子
  64. var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
  65. func GetRandString(size int) string {
  66. 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", "!", "@", "#", "$", "%", "^", "&", "*"}
  67. randomSb := ""
  68. digitSize := len(allLetterDigit)
  69. for i := 0; i < size; i++ {
  70. randomSb += allLetterDigit[rnd.Intn(digitSize)]
  71. }
  72. return randomSb
  73. }
  74. func GetRandStringNoSpecialChar(size int) string {
  75. 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"}
  76. randomSb := ""
  77. digitSize := len(allLetterDigit)
  78. for i := 0; i < size; i++ {
  79. randomSb += allLetterDigit[rnd.Intn(digitSize)]
  80. }
  81. return randomSb
  82. }
  83. func StringsToJSON(str string) string {
  84. rs := []rune(str)
  85. jsons := ""
  86. for _, r := range rs {
  87. rint := int(r)
  88. if rint < 128 {
  89. jsons += string(r)
  90. } else {
  91. jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
  92. }
  93. }
  94. return jsons
  95. }
  96. // 序列化
  97. func ToString(v interface{}) string {
  98. data, _ := json.Marshal(v)
  99. return string(data)
  100. }
  101. // md5加密
  102. func MD5(data string) string {
  103. m := md5.Sum([]byte(data))
  104. return hex.EncodeToString(m[:])
  105. }
  106. // 获取数字随机字符
  107. func GetRandDigit(n int) string {
  108. return fmt.Sprintf("%0"+strconv.Itoa(n)+"d", rnd.Intn(int(math.Pow10(n))))
  109. }
  110. // 获取随机数
  111. func GetRandNumber(n int) int {
  112. return rnd.Intn(n)
  113. }
  114. func GetRandInt(min, max int) int {
  115. if min >= max || min == 0 || max == 0 {
  116. return max
  117. }
  118. return rand.Intn(max-min) + min
  119. }
  120. func GetToday(format string) string {
  121. today := time.Now().Format(format)
  122. return today
  123. }
  124. // 获取今天剩余秒数
  125. func GetTodayLastSecond() time.Duration {
  126. today := GetToday(FormatDate) + " 23:59:59"
  127. end, _ := time.ParseInLocation(FormatDateTime, today, time.Local)
  128. return time.Duration(end.Unix()-time.Now().Local().Unix()) * time.Second
  129. }
  130. // 处理出生日期函数
  131. func GetBrithDate(idcard string) string {
  132. l := len(idcard)
  133. var s string
  134. if l == 15 {
  135. s = "19" + idcard[6:8] + "-" + idcard[8:10] + "-" + idcard[10:12]
  136. return s
  137. }
  138. if l == 18 {
  139. s = idcard[6:10] + "-" + idcard[10:12] + "-" + idcard[12:14]
  140. return s
  141. }
  142. return GetToday(FormatDate)
  143. }
  144. // 处理性别
  145. func WhichSexByIdcard(idcard string) string {
  146. var sexs = [2]string{"女", "男"}
  147. length := len(idcard)
  148. if length == 18 {
  149. sex, _ := strconv.Atoi(string(idcard[16]))
  150. return sexs[sex%2]
  151. } else if length == 15 {
  152. sex, _ := strconv.Atoi(string(idcard[14]))
  153. return sexs[sex%2]
  154. }
  155. return "男"
  156. }
  157. // 截取小数点后几位
  158. func SubFloatToString(f float64, m int) string {
  159. n := strconv.FormatFloat(f, 'f', -1, 64)
  160. if n == "" {
  161. return ""
  162. }
  163. if m >= len(n) {
  164. return n
  165. }
  166. newn := strings.Split(n, ".")
  167. if m == 0 {
  168. return newn[0]
  169. }
  170. if len(newn) < 2 || m >= len(newn[1]) {
  171. return n
  172. }
  173. return newn[0] + "." + newn[1][:m]
  174. }
  175. // 截取小数点后几位
  176. func SubFloatToFloat(f float64, m int) float64 {
  177. newn := SubFloatToString(f, m)
  178. newf, _ := strconv.ParseFloat(newn, 64)
  179. return newf
  180. }
  181. // 截取小数点后几位
  182. func SubFloatToFloatStr(f float64, m int) string {
  183. newn := SubFloatToString(f, m)
  184. return newn
  185. }
  186. // 获取相差时间-年
  187. func GetYearDiffer(start_time, end_time string) int {
  188. t1, _ := time.ParseInLocation("2006-01-02", start_time, time.Local)
  189. t2, _ := time.ParseInLocation("2006-01-02", end_time, time.Local)
  190. age := t2.Year() - t1.Year()
  191. if t2.Month() < t1.Month() || (t2.Month() == t1.Month() && t2.Day() < t1.Day()) {
  192. age--
  193. }
  194. return age
  195. }
  196. // 获取相差时间-秒
  197. func GetSecondDifferByTime(start_time, end_time time.Time) int64 {
  198. diff := end_time.Unix() - start_time.Unix()
  199. return diff
  200. }
  201. func FixFloat(f float64, m int) float64 {
  202. newn := SubFloatToString(f+0.00000001, m)
  203. newf, _ := strconv.ParseFloat(newn, 64)
  204. return newf
  205. }
  206. // 将字符串数组转化为逗号分割的字符串形式 ["str1","str2","str3"] >>> "str1,str2,str3"
  207. func StrListToString(strList []string) (str string) {
  208. if len(strList) > 0 {
  209. for k, v := range strList {
  210. if k == 0 {
  211. str = v
  212. } else {
  213. str = str + "," + v
  214. }
  215. }
  216. return
  217. }
  218. return ""
  219. }
  220. // 数据没有记录
  221. func ErrNoRow() string {
  222. return "<QuerySeter> no row found"
  223. }
  224. // 判断文件是否存在
  225. func FileIsExist(filePath string) bool {
  226. _, err := os.Stat(filePath)
  227. return err == nil || os.IsExist(err)
  228. }
  229. // 获取图片扩展名
  230. func GetImgExt(file string) (ext string, err error) {
  231. var headerByte []byte
  232. headerByte = make([]byte, 8)
  233. fd, err := os.Open(file)
  234. if err != nil {
  235. return "", err
  236. }
  237. defer fd.Close()
  238. _, err = fd.Read(headerByte)
  239. if err != nil {
  240. return "", err
  241. }
  242. xStr := fmt.Sprintf("%x", headerByte)
  243. switch {
  244. case xStr == "89504e470d0a1a0a":
  245. ext = ".png"
  246. case xStr == "0000010001002020":
  247. ext = ".ico"
  248. case xStr == "0000020001002020":
  249. ext = ".cur"
  250. case xStr[:12] == "474946383961" || xStr[:12] == "474946383761":
  251. ext = ".gif"
  252. case xStr[:10] == "0000020000" || xStr[:10] == "0000100000":
  253. ext = ".tga"
  254. case xStr[:8] == "464f524d":
  255. ext = ".iff"
  256. case xStr[:8] == "52494646":
  257. ext = ".ani"
  258. case xStr[:4] == "4d4d" || xStr[:4] == "4949":
  259. ext = ".tiff"
  260. case xStr[:4] == "424d":
  261. ext = ".bmp"
  262. case xStr[:4] == "ffd8":
  263. ext = ".jpg"
  264. case xStr[:2] == "0a":
  265. ext = ".pcx"
  266. default:
  267. ext = ""
  268. }
  269. return ext, nil
  270. }
  271. // 保存图片
  272. func SaveImage(path string, img image.Image) (err error) {
  273. //需要保持的文件
  274. imgfile, err := os.Create(path)
  275. defer imgfile.Close()
  276. // 以PNG格式保存文件
  277. err = png.Encode(imgfile, img)
  278. return err
  279. }
  280. // 下载图片
  281. func DownloadImage(imgUrl string) (filePath string, err error) {
  282. imgPath := "./static/imgs/"
  283. fileName := path.Base(imgUrl)
  284. res, err := http.Get(imgUrl)
  285. if err != nil {
  286. fmt.Println("A error occurred!")
  287. return
  288. }
  289. defer res.Body.Close()
  290. // 获得get请求响应的reader对象
  291. reader := bufio.NewReaderSize(res.Body, 32*1024)
  292. filePath = imgPath + fileName
  293. file, err := os.Create(filePath)
  294. if err != nil {
  295. return
  296. }
  297. // 获得文件的writer对象
  298. writer := bufio.NewWriter(file)
  299. written, _ := io.Copy(writer, reader)
  300. fmt.Printf("Total length: %d \n", written)
  301. return
  302. }
  303. // 保存base64数据为文件
  304. func SaveBase64ToFile(content, path string) error {
  305. data, err := base64.StdEncoding.DecodeString(content)
  306. if err != nil {
  307. return err
  308. }
  309. f, err := os.Create(path)
  310. defer f.Close()
  311. if err != nil {
  312. return err
  313. }
  314. f.Write(data)
  315. return nil
  316. }
  317. func SaveBase64ToFileBySeek(content, path string) (err error) {
  318. data, err := base64.StdEncoding.DecodeString(content)
  319. exist, err := PathExists(path)
  320. if err != nil {
  321. return
  322. }
  323. if !exist {
  324. f, err := os.Create(path)
  325. if err != nil {
  326. return err
  327. }
  328. n, _ := f.Seek(0, 2)
  329. // 从末尾的偏移量开始写入内容
  330. _, err = f.WriteAt([]byte(data), n)
  331. defer f.Close()
  332. } else {
  333. f, err := os.OpenFile(path, os.O_WRONLY, 0644)
  334. if err != nil {
  335. return err
  336. }
  337. n, _ := f.Seek(0, 2)
  338. // 从末尾的偏移量开始写入内容
  339. _, err = f.WriteAt([]byte(data), n)
  340. defer f.Close()
  341. }
  342. return nil
  343. }
  344. func PathExists(path string) (bool, error) {
  345. _, err := os.Stat(path)
  346. if err == nil {
  347. return true, nil
  348. }
  349. if os.IsNotExist(err) {
  350. return false, nil
  351. }
  352. return false, err
  353. }
  354. func StartIndex(page, pagesize int) int {
  355. if page > 1 {
  356. return (page - 1) * pagesize
  357. }
  358. return 0
  359. }
  360. func PageCount(count, pagesize int) int {
  361. if count%pagesize > 0 {
  362. return count/pagesize + 1
  363. } else {
  364. return count / pagesize
  365. }
  366. }
  367. func TrimHtml(src string) string {
  368. //将HTML标签全转换成小写
  369. re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
  370. src = re.ReplaceAllStringFunc(src, strings.ToLower)
  371. re, _ = regexp.Compile("\\<img[\\S\\s]+?\\>")
  372. src = re.ReplaceAllString(src, "[图片]")
  373. re, _ = regexp.Compile("class[\\S\\s]+?>")
  374. src = re.ReplaceAllString(src, "")
  375. re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
  376. src = re.ReplaceAllString(src, "")
  377. return strings.TrimSpace(src)
  378. }
  379. //1556164246 -> 2019-04-25 03:50:46 +0000
  380. //timestamp
  381. func TimeToTimestamp() {
  382. fmt.Println(time.Unix(1556164246, 0).Format("2006-01-02 15:04:05"))
  383. }
  384. func ToUnicode(text string) string {
  385. textQuoted := strconv.QuoteToASCII(text)
  386. textUnquoted := textQuoted[1 : len(textQuoted)-1]
  387. return textUnquoted
  388. }
  389. func VersionToInt(version string) int {
  390. version = strings.Replace(version, ".", "", -1)
  391. n, _ := strconv.Atoi(version)
  392. return n
  393. }
  394. func IsCheckInList(list []int, s int) bool {
  395. for _, v := range list {
  396. if v == s {
  397. return true
  398. }
  399. }
  400. return false
  401. }
  402. func round(num float64) int {
  403. return int(num + math.Copysign(0.5, num))
  404. }
  405. func toFixed(num float64, precision int) float64 {
  406. output := math.Pow(10, float64(precision))
  407. return float64(round(num*output)) / output
  408. }
  409. // GetWilsonScore returns Wilson Score
  410. func GetWilsonScore(p, n float64) float64 {
  411. if p == 0 && n == 0 {
  412. return 0
  413. }
  414. 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)
  415. }
  416. // 将中文数字转化成数字,比如 第三百四十五章,返回第345章 不支持一亿及以上
  417. func ChangeWordsToNum(str string) (numStr string) {
  418. words := ([]rune)(str)
  419. num := 0
  420. n := 0
  421. for i := 0; i < len(words); i++ {
  422. word := string(words[i : i+1])
  423. switch word {
  424. case "万":
  425. if n == 0 {
  426. n = 1
  427. }
  428. n = n * 10000
  429. num = num*10000 + n
  430. n = 0
  431. case "千":
  432. if n == 0 {
  433. n = 1
  434. }
  435. n = n * 1000
  436. num += n
  437. n = 0
  438. case "百":
  439. if n == 0 {
  440. n = 1
  441. }
  442. n = n * 100
  443. num += n
  444. n = 0
  445. case "十":
  446. if n == 0 {
  447. n = 1
  448. }
  449. n = n * 10
  450. num += n
  451. n = 0
  452. case "一":
  453. n += 1
  454. case "二":
  455. n += 2
  456. case "三":
  457. n += 3
  458. case "四":
  459. n += 4
  460. case "五":
  461. n += 5
  462. case "六":
  463. n += 6
  464. case "七":
  465. n += 7
  466. case "八":
  467. n += 8
  468. case "九":
  469. n += 9
  470. case "零":
  471. default:
  472. if n > 0 {
  473. num += n
  474. n = 0
  475. }
  476. if num == 0 {
  477. numStr += word
  478. } else {
  479. numStr += strconv.Itoa(num) + word
  480. num = 0
  481. }
  482. }
  483. }
  484. if n > 0 {
  485. num += n
  486. n = 0
  487. }
  488. if num != 0 {
  489. numStr += strconv.Itoa(num)
  490. }
  491. return
  492. }
  493. func Sha1(data string) string {
  494. sha1 := sha1.New()
  495. sha1.Write([]byte(data))
  496. return hex.EncodeToString(sha1.Sum([]byte("")))
  497. }
  498. func GetVideoPlaySeconds(videoPath string) (playSeconds float64, err error) {
  499. cmd := `ffmpeg -i ` + videoPath + ` 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//`
  500. out, err := exec.Command("bash", "-c", cmd).Output()
  501. if err != nil {
  502. return
  503. }
  504. outTimes := string(out)
  505. fmt.Println("outTimes:", outTimes)
  506. if outTimes != "" {
  507. timeArr := strings.Split(outTimes, ":")
  508. h := timeArr[0]
  509. m := timeArr[1]
  510. s := timeArr[2]
  511. hInt, err := strconv.Atoi(h)
  512. if err != nil {
  513. return playSeconds, err
  514. }
  515. mInt, err := strconv.Atoi(m)
  516. if err != nil {
  517. return playSeconds, err
  518. }
  519. s = strings.Trim(s, " ")
  520. s = strings.Trim(s, "\n")
  521. sInt, err := strconv.ParseFloat(s, 64)
  522. if err != nil {
  523. return playSeconds, err
  524. }
  525. playSeconds = float64(hInt)*3600 + float64(mInt)*60 + float64(sInt)
  526. }
  527. return
  528. }
  529. func GetMaxTradeCode(tradeCode string) (maxTradeCode string, err error) {
  530. tradeCode = strings.Replace(tradeCode, "W", "", -1)
  531. tradeCode = strings.Trim(tradeCode, " ")
  532. tradeCodeInt, err := strconv.Atoi(tradeCode)
  533. if err != nil {
  534. return
  535. }
  536. tradeCodeInt = tradeCodeInt + 1
  537. maxTradeCode = fmt.Sprintf("W%06d", tradeCodeInt)
  538. return
  539. }
  540. // excel日期字段格式化 yyyy-mm-dd
  541. func ConvertToFormatDay(excelDaysString string) string {
  542. // 2006-01-02 距离 1900-01-01的天数
  543. baseDiffDay := 38719 //在网上工具计算的天数需要加2天,什么原因没弄清楚
  544. curDiffDay := excelDaysString
  545. b, _ := strconv.Atoi(curDiffDay)
  546. // 获取excel的日期距离2006-01-02的天数
  547. realDiffDay := b - baseDiffDay
  548. //fmt.Println("realDiffDay:",realDiffDay)
  549. // 距离2006-01-02 秒数
  550. realDiffSecond := realDiffDay * 24 * 3600
  551. //fmt.Println("realDiffSecond:",realDiffSecond)
  552. // 2006-01-02 15:04:05距离1970-01-01 08:00:00的秒数 网上工具可查出
  553. baseOriginSecond := 1136185445
  554. resultTime := time.Unix(int64(baseOriginSecond+realDiffSecond), 0).Format("2006-01-02")
  555. return resultTime
  556. }
  557. func CheckPwd(pwd string) bool {
  558. compile := `([0-9a-z]+){6,12}|(a-z0-9]+){6,12}`
  559. reg := regexp.MustCompile(compile)
  560. flag := reg.MatchString(pwd)
  561. return flag
  562. }
  563. func GetMonthStartAndEnd(myYear string, myMonth string) (startDate, endDate string) {
  564. // 数字月份必须前置补零
  565. if len(myMonth) == 1 {
  566. myMonth = "0" + myMonth
  567. }
  568. yInt, _ := strconv.Atoi(myYear)
  569. timeLayout := "2006-01-02 15:04:05"
  570. loc, _ := time.LoadLocation("Local")
  571. theTime, _ := time.ParseInLocation(timeLayout, myYear+"-"+myMonth+"-01 00:00:00", loc)
  572. newMonth := theTime.Month()
  573. t1 := time.Date(yInt, newMonth, 1, 0, 0, 0, 0, time.Local).Format("2006-01-02")
  574. t2 := time.Date(yInt, newMonth+1, 0, 0, 0, 0, 0, time.Local).Format("2006-01-02")
  575. return t1, t2
  576. }
  577. // 移除字符串中的空格
  578. func TrimStr(str string) (str2 string) {
  579. if str == "" {
  580. return str
  581. }
  582. return strings.Replace(str, " ", "", -1)
  583. }
  584. // 字符串转换为time
  585. func StrTimeToTime(strTime string) time.Time {
  586. timeLayout := "2006-01-02 15:04:05" //转化所需模板
  587. loc, _ := time.LoadLocation("Local") //重要:获取时区
  588. resultTime, _ := time.ParseInLocation(timeLayout, strTime, loc)
  589. return resultTime
  590. }
  591. // 字符串类型时间转周几
  592. func StrDateTimeToWeek(strTime string) string {
  593. var WeekDayMap = map[string]string{
  594. "Monday": "周一",
  595. "Tuesday": "周二",
  596. "Wednesday": "周三",
  597. "Thursday": "周四",
  598. "Friday": "周五",
  599. "Saturday": "周六",
  600. "Sunday": "周日",
  601. }
  602. var ctime = StrTimeToTime(strTime).Format("2006-01-02")
  603. startday, _ := time.ParseInLocation("2006-01-02", ctime, time.Local)
  604. staweek_int := startday.Weekday().String()
  605. return WeekDayMap[staweek_int]
  606. }
  607. // 时间格式转年月日字符串
  608. func TimeToStrYmd(time2 time.Time) string {
  609. var Ymd string
  610. year := time2.Year()
  611. month := time2.Format("1")
  612. day1 := time.Now().Day()
  613. Ymd = strconv.Itoa(year) + "年" + month + "月" + strconv.Itoa(day1) + "日"
  614. return Ymd
  615. }
  616. // 时间格式去掉时分秒
  617. func TimeRemoveHms(strTime string) string {
  618. var Ymd string
  619. var resultTime = StrTimeToTime(strTime)
  620. year := resultTime.Year()
  621. month := resultTime.Format("01")
  622. day1 := resultTime.Day()
  623. Ymd = strconv.Itoa(year) + "." + month + "." + strconv.Itoa(day1)
  624. return Ymd
  625. }
  626. // 时间格式去掉时分秒
  627. func TimeRemoveHms2(strTime string) string {
  628. var Ymd string
  629. var resultTime = StrTimeToTime(strTime)
  630. year := resultTime.Year()
  631. month := resultTime.Format("01")
  632. day1 := resultTime.Day()
  633. Ymd = strconv.Itoa(year) + "-" + month + "-" + strconv.Itoa(day1)
  634. return Ymd
  635. }
  636. // 文章上一次编辑时间
  637. func ArticleLastTime(strTime string) string {
  638. var newTime string
  639. stamp, _ := time.ParseInLocation("2006-01-02 15:04:05", strTime, time.Local)
  640. diffTime := time.Now().Unix() - stamp.Unix()
  641. if diffTime <= 60 {
  642. newTime = "当前"
  643. } else if diffTime < 60*60 {
  644. newTime = strconv.FormatInt(diffTime/60, 10) + "分钟前"
  645. } else if diffTime < 24*60*60 {
  646. newTime = strconv.FormatInt(diffTime/(60*60), 10) + "小时前"
  647. } else if diffTime < 30*24*60*60 {
  648. newTime = strconv.FormatInt(diffTime/(24*60*60), 10) + "天前"
  649. } else if diffTime < 12*30*24*60*60 {
  650. newTime = strconv.FormatInt(diffTime/(30*24*60*60), 10) + "月前"
  651. } else {
  652. newTime = "1年前"
  653. }
  654. return newTime
  655. }
  656. // 人民币小写转大写
  657. func ConvertNumToCny(num float64) (str string, err error) {
  658. strNum := strconv.FormatFloat(num*100, 'f', 0, 64)
  659. sliceUnit := []string{"仟", "佰", "拾", "亿", "仟", "佰", "拾", "万", "仟", "佰", "拾", "元", "角", "分"}
  660. // log.Println(sliceUnit[:len(sliceUnit)-2])
  661. s := sliceUnit[len(sliceUnit)-len(strNum):]
  662. upperDigitUnit := map[string]string{"0": "零", "1": "壹", "2": "贰", "3": "叁", "4": "肆", "5": "伍", "6": "陆", "7": "柒", "8": "捌", "9": "玖"}
  663. for k, v := range strNum[:] {
  664. str = str + upperDigitUnit[string(v)] + s[k]
  665. }
  666. reg, err := regexp.Compile(`零角零分$`)
  667. str = reg.ReplaceAllString(str, "整")
  668. reg, err = regexp.Compile(`零角`)
  669. str = reg.ReplaceAllString(str, "零")
  670. reg, err = regexp.Compile(`零分$`)
  671. str = reg.ReplaceAllString(str, "整")
  672. reg, err = regexp.Compile(`零[仟佰拾]`)
  673. str = reg.ReplaceAllString(str, "零")
  674. reg, err = regexp.Compile(`零{2,}`)
  675. str = reg.ReplaceAllString(str, "零")
  676. reg, err = regexp.Compile(`零亿`)
  677. str = reg.ReplaceAllString(str, "亿")
  678. reg, err = regexp.Compile(`零万`)
  679. str = reg.ReplaceAllString(str, "万")
  680. reg, err = regexp.Compile(`零*元`)
  681. str = reg.ReplaceAllString(str, "元")
  682. reg, err = regexp.Compile(`亿零{0, 3}万`)
  683. str = reg.ReplaceAllString(str, "^元")
  684. reg, err = regexp.Compile(`零元`)
  685. str = reg.ReplaceAllString(str, "零")
  686. return
  687. }
  688. // GetNowWeekMonday 获取本周周一的时间
  689. func GetNowWeekMonday() time.Time {
  690. offset := int(time.Monday - time.Now().Weekday())
  691. if offset == 1 { //正好是周日,但是按照中国人的理解,周日是一周最后一天,而不是一周开始的第一天
  692. offset = -6
  693. }
  694. mondayTime := time.Now().AddDate(0, 0, offset)
  695. mondayTime = time.Date(mondayTime.Year(), mondayTime.Month(), mondayTime.Day(), 0, 0, 0, 0, mondayTime.Location())
  696. return mondayTime
  697. }
  698. // GetNowWeekLastDay 获取本周最后一天的时间
  699. func GetNowWeekLastDay() time.Time {
  700. offset := int(time.Monday - time.Now().Weekday())
  701. if offset == 1 { //正好是周日,但是按照中国人的理解,周日是一周最后一天,而不是一周开始的第一天
  702. offset = -6
  703. }
  704. firstDayTime := time.Now().AddDate(0, 0, offset)
  705. firstDayTime = time.Date(firstDayTime.Year(), firstDayTime.Month(), firstDayTime.Day(), 0, 0, 0, 0, firstDayTime.Location()).AddDate(0, 0, 6)
  706. lastDayTime := time.Date(firstDayTime.Year(), firstDayTime.Month(), firstDayTime.Day(), 23, 59, 59, 0, firstDayTime.Location())
  707. return lastDayTime
  708. }
  709. // GetNowMonthFirstDay 获取本月第一天的时间
  710. func GetNowMonthFirstDay() time.Time {
  711. nowMonthFirstDay := time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.Now().Location())
  712. return nowMonthFirstDay
  713. }
  714. // GetNowMonthLastDay 获取本月最后一天的时间
  715. func GetNowMonthLastDay() time.Time {
  716. nowMonthLastDay := time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 1, -1)
  717. nowMonthLastDay = time.Date(nowMonthLastDay.Year(), nowMonthLastDay.Month(), nowMonthLastDay.Day(), 23, 59, 59, 0, nowMonthLastDay.Location())
  718. return nowMonthLastDay
  719. }
  720. // GetNowQuarterFirstDay 获取本季度第一天的时间
  721. func GetNowQuarterFirstDay() time.Time {
  722. month := int(time.Now().Month())
  723. var nowQuarterFirstDay time.Time
  724. if month >= 1 && month <= 3 {
  725. //1月1号
  726. nowQuarterFirstDay = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
  727. } else if month >= 4 && month <= 6 {
  728. //4月1号
  729. nowQuarterFirstDay = time.Date(time.Now().Year(), 4, 1, 0, 0, 0, 0, time.Now().Location())
  730. } else if month >= 7 && month <= 9 {
  731. nowQuarterFirstDay = time.Date(time.Now().Year(), 7, 1, 0, 0, 0, 0, time.Now().Location())
  732. } else {
  733. nowQuarterFirstDay = time.Date(time.Now().Year(), 10, 1, 0, 0, 0, 0, time.Now().Location())
  734. }
  735. return nowQuarterFirstDay
  736. }
  737. // GetNowQuarterLastDay 获取本季度最后一天的时间
  738. func GetNowQuarterLastDay() time.Time {
  739. month := int(time.Now().Month())
  740. var nowQuarterLastDay time.Time
  741. if month >= 1 && month <= 3 {
  742. //03-31 23:59:59
  743. nowQuarterLastDay = time.Date(time.Now().Year(), 3, 31, 23, 59, 59, 0, time.Now().Location())
  744. } else if month >= 4 && month <= 6 {
  745. //06-30 23:59:59
  746. nowQuarterLastDay = time.Date(time.Now().Year(), 6, 30, 23, 59, 59, 0, time.Now().Location())
  747. } else if month >= 7 && month <= 9 {
  748. //09-30 23:59:59
  749. nowQuarterLastDay = time.Date(time.Now().Year(), 9, 30, 23, 59, 59, 0, time.Now().Location())
  750. } else {
  751. //12-31 23:59:59
  752. nowQuarterLastDay = time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
  753. }
  754. return nowQuarterLastDay
  755. }
  756. // GetNowHalfYearFirstDay 获取当前半年的第一天的时间
  757. func GetNowHalfYearFirstDay() time.Time {
  758. month := int(time.Now().Month())
  759. var nowHalfYearLastDay time.Time
  760. if month >= 1 && month <= 6 {
  761. //03-31 23:59:59
  762. nowHalfYearLastDay = time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
  763. } else {
  764. //12-31 23:59:59
  765. nowHalfYearLastDay = time.Date(time.Now().Year(), 7, 1, 0, 0, 0, 0, time.Now().Location())
  766. }
  767. return nowHalfYearLastDay
  768. }
  769. // GetNowHalfYearLastDay 获取当前半年的最后一天的时间
  770. func GetNowHalfYearLastDay() time.Time {
  771. month := int(time.Now().Month())
  772. var nowHalfYearLastDay time.Time
  773. if month >= 1 && month <= 6 {
  774. //03-31 23:59:59
  775. nowHalfYearLastDay = time.Date(time.Now().Year(), 6, 30, 23, 59, 59, 0, time.Now().Location())
  776. } else {
  777. //12-31 23:59:59
  778. nowHalfYearLastDay = time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
  779. }
  780. return nowHalfYearLastDay
  781. }
  782. // GetNowYearFirstDay 获取当前年的最后一天的时间
  783. func GetNowYearFirstDay() time.Time {
  784. //12-31 23:59:59
  785. nowYearFirstDay := time.Date(time.Now().Year(), 1, 1, 0, 0, 0, 0, time.Now().Location())
  786. return nowYearFirstDay
  787. }
  788. // GetNowYearLastDay 获取当前年的最后一天的时间
  789. func GetNowYearLastDay() time.Time {
  790. //12-31 23:59:59
  791. nowYearLastDay := time.Date(time.Now().Year(), 12, 31, 23, 59, 59, 0, time.Now().Location())
  792. return nowYearLastDay
  793. }
  794. // CalculationDate 计算两个日期之间相差n年m月y天
  795. func CalculationDate(startDate, endDate time.Time) (beetweenDay string, err error) {
  796. //startDate := time.Date(2021, 3, 28, 0, 0, 0, 0, time.Now().Location())
  797. //endDate := time.Date(2022, 3, 31, 0, 0, 0, 0, time.Now().Location())
  798. numYear := endDate.Year() - startDate.Year()
  799. numMonth := int(endDate.Month()) - int(startDate.Month())
  800. numDay := 0
  801. //获取截止月的总天数
  802. endDateDays := getMonthDay(endDate.Year(), int(endDate.Month()))
  803. //获取截止月的前一个月
  804. endDatePrevMonthDate := endDate.AddDate(0, -1, 0)
  805. //获取截止日期的上一个月的总天数
  806. endDatePrevMonthDays := getMonthDay(endDatePrevMonthDate.Year(), int(endDatePrevMonthDate.Month()))
  807. //获取开始日期的的月份总天数
  808. startDateMonthDays := getMonthDay(startDate.Year(), int(startDate.Month()))
  809. //判断,截止月是否完全被选中,如果相等,那么代表截止月份全部天数被选择
  810. if endDate.Day() == endDateDays {
  811. numDay = startDateMonthDays - startDate.Day() + 1
  812. //如果剩余天数正好与开始日期的天数是一致的,那么月份加1
  813. if numDay == startDateMonthDays {
  814. numMonth++
  815. numDay = 0
  816. //超过月份了,那么年份加1
  817. if numMonth == 12 {
  818. numYear++
  819. numMonth = 0
  820. }
  821. }
  822. } else {
  823. numDay = endDate.Day() - startDate.Day() + 1
  824. }
  825. //天数小于0,那么向月份借一位
  826. if numDay < 0 {
  827. //向上一个月借一个月的天数
  828. numDay += endDatePrevMonthDays
  829. //总月份减去一个月
  830. numMonth = numMonth - 1
  831. }
  832. //月份小于0,那么向年份借一位
  833. if numMonth < 0 {
  834. //向上一个年借12个月
  835. numMonth += 12
  836. //总年份减去一年
  837. numYear = numYear - 1
  838. }
  839. if numYear < 0 {
  840. err = errors.New("日期异常")
  841. return
  842. }
  843. if numYear > 0 {
  844. beetweenDay += fmt.Sprint(numYear, "年")
  845. }
  846. if numMonth > 0 {
  847. beetweenDay += fmt.Sprint(numMonth, "个月")
  848. }
  849. if numDay > 0 {
  850. beetweenDay += fmt.Sprint(numDay, "天")
  851. }
  852. return
  853. }
  854. // FormatPrice 格式化展示金额数字(财务金额展示,小数点前,每三位用,隔开) 1,234,567,898.55
  855. func FormatPrice(price float64) (str string) {
  856. str = decimal.NewFromFloat(price).String()
  857. length := len(str)
  858. if length < 4 {
  859. return str
  860. }
  861. arr := strings.Split(str, ".") //用小数点符号分割字符串,为数组接收
  862. length1 := len(arr[0])
  863. if length1 < 4 {
  864. return str
  865. }
  866. count := (length1 - 1) / 3
  867. for i := 0; i < count; i++ {
  868. arr[0] = arr[0][:length1-(i+1)*3] + "," + arr[0][length1-(i+1)*3:]
  869. }
  870. return strings.Join(arr, ".") //将一系列字符串连接为一个字符串,之间用sep来分隔。
  871. }
  872. // getMonthDay 获取某年某月有多少天
  873. func getMonthDay(year, month int) (days int) {
  874. if month != 2 {
  875. if month == 4 || month == 6 || month == 9 || month == 11 {
  876. days = 30
  877. } else {
  878. days = 31
  879. }
  880. } else {
  881. if ((year%4) == 0 && (year%100) != 0) || (year%400) == 0 {
  882. days = 29
  883. } else {
  884. days = 28
  885. }
  886. }
  887. return
  888. }
  889. func SaveToFile(content, path string) error {
  890. f, err := os.Create(path)
  891. defer f.Close()
  892. if err != nil {
  893. return err
  894. }
  895. f.Write([]byte(content))
  896. return nil
  897. }
  898. // HideString 给字段加***(从字符串中间替换,少于需要替换的长度,那么就补全*的长度)
  899. // src 待*字符串
  900. // hideLen 需要加*的长度
  901. func HideString(src string, hideLen int) string {
  902. if src == "" {
  903. return src
  904. }
  905. str := []rune(src)
  906. if hideLen == 0 {
  907. hideLen = 4
  908. }
  909. hideStr := ""
  910. for i := 0; i < hideLen; i++ {
  911. hideStr += "*"
  912. }
  913. strLen := len(str)
  914. // 字符长度是1
  915. if strLen == 1 {
  916. return string(str[:1]) + hideStr
  917. }
  918. //字符长度大于1,但是小于等于需要隐藏的字符长度,那么就隐藏中间,保留前后各一位字符
  919. if strLen <= hideLen+2 {
  920. return string(str[:1]) + hideStr + string(str[strLen-1:])
  921. }
  922. subLen := strLen - hideLen //剩余需要展示的字符长度
  923. decimal.NewFromFloat(2)
  924. frontLenDecimal := decimal.NewFromInt(int64(subLen)).Div(decimal.NewFromInt(2)) //前面需要展示的字符的长度
  925. frontLen := frontLenDecimal.Floor().IntPart()
  926. return string(str[:frontLen]) + hideStr + string(str[frontLen+int64(hideLen):])
  927. }
  928. // 用户参会时间转换
  929. func GetAttendanceDetailSeconds(secondNum int) string {
  930. var timeStr string
  931. if secondNum <= 60 {
  932. if secondNum < 10 {
  933. timeStr = "0" + strconv.Itoa(secondNum) + "''"
  934. } else {
  935. timeStr = strconv.Itoa(secondNum) + "''"
  936. }
  937. } else {
  938. var remainderStr string
  939. remainderNum := secondNum % 60
  940. minuteNum := secondNum / 60
  941. if remainderNum < 10 {
  942. remainderStr = "0" + strconv.Itoa(remainderNum) + "''"
  943. } else {
  944. remainderStr = strconv.Itoa(remainderNum) + "''"
  945. }
  946. if minuteNum < 10 {
  947. timeStr = "0" + strconv.Itoa(minuteNum) + "'" + remainderStr
  948. } else {
  949. timeStr = strconv.Itoa(minuteNum) + "'" + remainderStr
  950. }
  951. }
  952. return timeStr
  953. }
  954. // SubStr 截取字符串(中文)
  955. func SubStr(str string, subLen int) string {
  956. strRune := []rune(str)
  957. bodyRuneLen := len(strRune)
  958. if bodyRuneLen > subLen {
  959. bodyRuneLen = subLen
  960. }
  961. str = string(strRune[:bodyRuneLen])
  962. return str
  963. }
  964. func GetLocalIP() (ip string, err error) {
  965. addrs, err := net.InterfaceAddrs()
  966. if err != nil {
  967. return
  968. }
  969. for _, addr := range addrs {
  970. ipAddr, ok := addr.(*net.IPNet)
  971. if !ok {
  972. continue
  973. }
  974. if ipAddr.IP.IsLoopback() {
  975. continue
  976. }
  977. if !ipAddr.IP.IsGlobalUnicast() {
  978. continue
  979. }
  980. return ipAddr.IP.String(), nil
  981. }
  982. return
  983. }
  984. func PrintLog(params ...string) {
  985. _, file, line, ok := runtime.Caller(1)
  986. fmt.Println(file, line, ok, params)
  987. }
  988. // InArrayByStr php中的in_array(判断String类型的切片中是否存在该string值)
  989. func InArrayByStr(idStrList []string, searchId string) (has bool) {
  990. for _, id := range idStrList {
  991. if id == searchId {
  992. has = true
  993. return
  994. }
  995. }
  996. return
  997. }
  998. // InArrayByInt php中的in_array(判断Int类型的切片中是否存在该Int值)
  999. func InArrayByInt(idStrList []int, searchId int) (has bool) {
  1000. for _, id := range idStrList {
  1001. if id == searchId {
  1002. has = true
  1003. return
  1004. }
  1005. }
  1006. return
  1007. }
  1008. // GetOrmInReplace 获取orm的in查询替换?的方法
  1009. func GetOrmInReplace(num int) string {
  1010. template := make([]string, num)
  1011. for i := 0; i < num; i++ {
  1012. template[i] = "?"
  1013. }
  1014. return strings.Join(template, ",")
  1015. }
  1016. // GetTimeSubDay 计算两个时间的自然日期差
  1017. func GetTimeSubDay(t1, t2 time.Time) int {
  1018. var day int
  1019. swap := false
  1020. if t1.Unix() > t2.Unix() {
  1021. t1, t2 = t2, t1
  1022. swap = true
  1023. }
  1024. t1_ := t1.Add(time.Duration(t2.Sub(t1).Milliseconds()%86400000) * time.Millisecond)
  1025. day = int(t2.Sub(t1).Hours() / 24)
  1026. // 计算在t1+两个时间的余数之后天数是否有变化
  1027. if t1_.Day() != t1.Day() {
  1028. day += 1
  1029. }
  1030. if swap {
  1031. day = -day
  1032. }
  1033. return day
  1034. }
  1035. // GetFrequencyEndDay 根据当前时间和频度,获取该频度下最后一天的日期
  1036. func GetFrequencyEndDay(currDate time.Time, frequency string) (endDate time.Time) {
  1037. switch frequency {
  1038. case "周度":
  1039. // 如果当前就是最后一天,那么就直接返回本日期就好了
  1040. if currDate.Weekday() == 0 {
  1041. endDate = currDate
  1042. } else {
  1043. endDate = currDate.AddDate(0, 0, 7-int(currDate.Weekday()))
  1044. }
  1045. case "旬度":
  1046. nextDay := currDate.AddDate(0, 0, 1)
  1047. if nextDay.Day() == 1 || currDate.Day() == 10 || currDate.Day() == 20 {
  1048. //如果是每月10、20、最后一天,那么就直接返回本日期就好了
  1049. endDate = currDate
  1050. } else {
  1051. if currDate.Day() < 10 { // 每月10号
  1052. endDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, time.Local)
  1053. } else if currDate.Day() < 20 { // 每月10号
  1054. endDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, time.Local)
  1055. } else {
  1056. // 下旬,多种可能,最大天数可能存在8天,9天,10天,11天,
  1057. tmpNextMonth := currDate.AddDate(0, 0, 13)
  1058. endDate = time.Date(tmpNextMonth.Year(), tmpNextMonth.Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
  1059. }
  1060. }
  1061. case "月度":
  1062. nextDay := currDate.AddDate(0, 0, 1)
  1063. if nextDay.Day() == 1 {
  1064. //如果是每月的最后一天,那么就直接返回本日期就好了
  1065. endDate = currDate
  1066. } else {
  1067. endDate = time.Date(nextDay.Year(), nextDay.Month()+1, 1, 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
  1068. }
  1069. case "季度":
  1070. nextDay := currDate.AddDate(0, 0, 1)
  1071. if (nextDay.Month() == 1 || nextDay.Month() == 4 || nextDay.Month() == 7 || nextDay.Month() == 10) && nextDay.Day() == 1 {
  1072. //如果是每季的最后一天,那么就直接返回本日期就好了
  1073. endDate = currDate
  1074. } else {
  1075. if currDate.Month() < 4 { // 1季度
  1076. endDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, time.Local)
  1077. } else if currDate.Month() < 7 { // 2季度
  1078. endDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, time.Local)
  1079. } else if currDate.Month() < 10 { // 3季度
  1080. endDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, time.Local)
  1081. } else {
  1082. // 4季度
  1083. endDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, time.Local)
  1084. }
  1085. }
  1086. case "年度":
  1087. endDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, time.Local)
  1088. default:
  1089. endDate = currDate
  1090. return
  1091. }
  1092. return
  1093. }
  1094. // CheckFrequency 获取两个频度之间是否相对低高频
  1095. // 大于0,代表左侧是高频(例:左侧:日度,右侧:周度)
  1096. // 等于0,代表同频
  1097. // 小于0,代表右侧是高频(例:左侧:周度,右侧:日度)
  1098. func CheckFrequency(leftFrequency, rightFrequency string) int {
  1099. frequencyMap := map[string]int{
  1100. "年度": 0,
  1101. "半年度": 1,
  1102. "季度": 2,
  1103. "月度": 3,
  1104. "旬度": 4,
  1105. "周度": 5,
  1106. "日度": 6,
  1107. }
  1108. return frequencyMap[leftFrequency] - frequencyMap[rightFrequency]
  1109. }