gitea源码

time_str.go 2.0KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright 2024 Gitea. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package util
  4. import (
  5. "fmt"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. "sync"
  10. )
  11. type timeStrGlobalVarsType struct {
  12. units []struct {
  13. name string
  14. num int64
  15. }
  16. re *regexp.Regexp
  17. }
  18. // When tracking working time, only hour/minute/second units are accurate and could be used.
  19. // For other units like "day", it depends on "how many working hours in a day": 6 or 7 or 8?
  20. // So at the moment, we only support hour/minute/second units.
  21. // In the future, it could be some configurable options to help users
  22. // to convert the working time to different units.
  23. var timeStrGlobalVars = sync.OnceValue(func() *timeStrGlobalVarsType {
  24. v := &timeStrGlobalVarsType{}
  25. v.re = regexp.MustCompile(`(?i)(\d+)\s*([hms])`)
  26. v.units = []struct {
  27. name string
  28. num int64
  29. }{
  30. {"h", 60 * 60},
  31. {"m", 60},
  32. {"s", 1},
  33. }
  34. return v
  35. })
  36. func TimeEstimateParse(timeStr string) (int64, error) {
  37. if timeStr == "" {
  38. return 0, nil
  39. }
  40. var total int64
  41. matches := timeStrGlobalVars().re.FindAllStringSubmatchIndex(timeStr, -1)
  42. if len(matches) == 0 {
  43. return 0, fmt.Errorf("invalid time string: %s", timeStr)
  44. }
  45. if matches[0][0] != 0 || matches[len(matches)-1][1] != len(timeStr) {
  46. return 0, fmt.Errorf("invalid time string: %s", timeStr)
  47. }
  48. for _, match := range matches {
  49. amount, err := strconv.ParseInt(timeStr[match[2]:match[3]], 10, 64)
  50. if err != nil {
  51. return 0, fmt.Errorf("invalid time string: %v", err)
  52. }
  53. unit := timeStr[match[4]:match[5]]
  54. found := false
  55. for _, u := range timeStrGlobalVars().units {
  56. if strings.EqualFold(unit, u.name) {
  57. total += amount * u.num
  58. found = true
  59. break
  60. }
  61. }
  62. if !found {
  63. return 0, fmt.Errorf("invalid time unit: %s", unit)
  64. }
  65. }
  66. return total, nil
  67. }
  68. func TimeEstimateString(amount int64) string {
  69. var timeParts []string
  70. for _, u := range timeStrGlobalVars().units {
  71. if amount >= u.num {
  72. num := amount / u.num
  73. amount %= u.num
  74. timeParts = append(timeParts, fmt.Sprintf("%d%s", num, u.name))
  75. }
  76. }
  77. return strings.Join(timeParts, " ")
  78. }