parser.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package cronFormat
  2. import (
  3. "strings"
  4. cherryError "github.com/cherry-game/cherry/error"
  5. cherryString "github.com/cherry-game/cherry/extend/string"
  6. "github.com/spf13/cast"
  7. )
  8. const (
  9. questionMarkChar = "?"
  10. asteriskChar = "*"
  11. hyphenChar = "-"
  12. commaChar = ","
  13. slashChar = "/"
  14. colonChar = ":"
  15. )
  16. func getSpecHour(spec string) (int32, int32, error) {
  17. strSplit := strings.Split(spec, hyphenChar)
  18. if len(strSplit) != 2 {
  19. return 0, 0, cherryError.Errorf("parse error! [value = %s]", spec)
  20. }
  21. var (
  22. starOK bool
  23. endOK bool
  24. startSeconds int32
  25. endSeconds int32
  26. )
  27. startSeconds, starOK = toSeconds(strSplit[0])
  28. endSeconds, endOK = toSeconds(strSplit[1])
  29. if !starOK || !endOK {
  30. return 0, 0, cherryError.Errorf("parse error! [value = %s]", spec)
  31. }
  32. return startSeconds, endSeconds, nil
  33. }
  34. func toSeconds(specHour string) (int32, bool) {
  35. strSplit := strings.Split(specHour, colonChar)
  36. if len(strSplit) != 2 {
  37. return 0, false
  38. }
  39. hour, ok := cherryString.ToInt(strSplit[0])
  40. if !ok {
  41. return 0, false
  42. }
  43. if !hours.inRange(hour) {
  44. return 0, false
  45. }
  46. minute, ok := cherryString.ToInt(strSplit[1])
  47. if !ok {
  48. return 0, false
  49. }
  50. if !minutes.inRange(minute) {
  51. return 0, false
  52. }
  53. return int32((hour*60 + minute) * 60), true
  54. }
  55. func getSpec(spec string, b bounds) ([]int, error) {
  56. val, ok := isValue(spec, b)
  57. if ok {
  58. return val, nil
  59. }
  60. val, ok = isQuestionMark(spec, b)
  61. if ok {
  62. return val, nil
  63. }
  64. val, ok = isAsterisk(spec, b)
  65. if ok {
  66. return val, nil
  67. }
  68. val, ok = isHyphen(spec, b)
  69. if ok {
  70. return val, nil
  71. }
  72. val, ok = isComma(spec, b)
  73. if ok {
  74. return val, nil
  75. }
  76. val, ok = isSlash(spec, b)
  77. if ok {
  78. return val, nil
  79. }
  80. err := cherryError.Errorf("parse error! [value = %s]", spec)
  81. return nil, err
  82. }
  83. // isValue 解析 正常值格式
  84. func isValue(str string, b bounds) ([]int, bool) {
  85. intValue, ok := cherryString.ToInt(str)
  86. if !ok {
  87. return nil, false
  88. }
  89. if !b.inRange(intValue) {
  90. return nil, false
  91. }
  92. return []int{intValue}, true
  93. }
  94. // isQuestionMark 解析 ? 格式
  95. func isQuestionMark(str string, _ bounds) ([]int, bool) {
  96. if str == questionMarkChar {
  97. return []int{}, true
  98. }
  99. return nil, false
  100. }
  101. // isAsterisk 解析 * 格式
  102. func isAsterisk(str string, b bounds) ([]int, bool) {
  103. if str == asteriskChar {
  104. return b.all, true
  105. }
  106. return nil, false
  107. }
  108. // isHyphen 解析 - 格式
  109. func isHyphen(str string, b bounds) ([]int, bool) {
  110. if !strings.Contains(str, hyphenChar) {
  111. return nil, false
  112. }
  113. strSplit := strings.Split(str, hyphenChar)
  114. if len(strSplit) != 2 {
  115. return nil, false
  116. }
  117. start, e1 := cast.ToIntE(strSplit[0])
  118. end, e2 := cast.ToIntE(strSplit[1])
  119. if e1 != nil || e2 != nil {
  120. return nil, false
  121. }
  122. if start > end {
  123. return nil, false
  124. }
  125. if !b.inRange(start) {
  126. return nil, false
  127. }
  128. if !b.inRange(end) {
  129. return nil, false
  130. }
  131. var values []int
  132. for i := start; i <= end; i++ {
  133. values = append(values, i)
  134. }
  135. return values, true
  136. }
  137. // isComma 解析 , 格式
  138. func isComma(str string, b bounds) ([]int, bool) {
  139. if !strings.Contains(str, commaChar) {
  140. return nil, false
  141. }
  142. strSplit := strings.Split(str, commaChar)
  143. if len(strSplit) < 1 {
  144. return nil, false
  145. }
  146. var values []int
  147. for _, s := range strSplit {
  148. v, err := cast.ToIntE(s)
  149. if err != nil {
  150. return nil, false
  151. }
  152. if !b.inRange(v) {
  153. return nil, false
  154. }
  155. values = append(values, v)
  156. }
  157. return values, true
  158. }
  159. // isSlash 解析 / 格式
  160. func isSlash(str string, b bounds) ([]int, bool) {
  161. if !strings.Contains(str, slashChar) {
  162. return nil, false
  163. }
  164. strSplit := strings.Split(str, slashChar)
  165. if len(strSplit) != 2 {
  166. return nil, false
  167. }
  168. var values []int
  169. for _, s := range strSplit {
  170. v, err := cast.ToIntE(s)
  171. if err != nil {
  172. return nil, false
  173. }
  174. if !b.inRange(v) {
  175. return nil, false
  176. }
  177. values = append(values, v)
  178. }
  179. return values, true
  180. }