时间选定库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
5.8 KiB

5 years ago
5 years ago
5 years ago
  1. package time_arrow
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "sort"
  7. "strings"
  8. "time"
  9. )
  10. type TimeArrowType string
  11. const (
  12. TimeArrowTypeDayOfWeek TimeArrowType = "DAY_OF_WEEK"
  13. TimeArrowTypeDayOfMonth TimeArrowType = "DAY_OF_MONTH"
  14. TimeArrowTypeDateSlice TimeArrowType = "DATE_SLICE"
  15. )
  16. type DateSlice struct {
  17. Start string `json:"start"`
  18. End string `json:"end"`
  19. }
  20. type TimeArrow struct {
  21. Id int `json:"id"`
  22. Group string `json:"group"`
  23. Type TimeArrowType `json:"type"`
  24. //可选
  25. DayOfWeek []int `json:"day_of_week"`
  26. DayOfMonth []int `json:"day_of_month"`
  27. DateSlice []DateSlice `json:"date_slice"`
  28. //必选
  29. TimesOnDay []string `json:"times_on_day"`
  30. ExpandTags []string `json:"expand_tags"`
  31. ExpandValue interface{} `json:"expand_value"`
  32. Weights float64 `json:"weights"`
  33. }
  34. type TimeArrows []TimeArrow
  35. var GetData = func(group string) (TimeArrows, error) {
  36. return nil, errors.New("GetData 未实现")
  37. }
  38. func isInDateSlice(t time.Time, ta TimeArrow) bool {
  39. for e := range ta.DateSlice {
  40. startStr := ta.DateSlice[e].Start
  41. startSc := strings.Split(startStr, " ")
  42. if len(startSc) < 2 {
  43. startSc = append(startSc, "00:00:00")
  44. } else {
  45. startSc[1] = timeCompletion(startSc[1])
  46. }
  47. startStr = strings.Join(startSc, " ")
  48. endStr := ta.DateSlice[e].End
  49. endSc := strings.Split(endStr, " ")
  50. if len(endSc) < 2 {
  51. endSc = append(endSc, "00:00:00")
  52. } else {
  53. endSc[1] = timeCompletion(endSc[1])
  54. }
  55. endStr = strings.Join(endSc, " ")
  56. startTime, err := time.Parse("2006-01-02 15:04:05", startStr)
  57. if err != nil {
  58. log.Println("时间段开始时间格式错误", startStr)
  59. continue
  60. }
  61. endTime, err := time.Parse("2006-01-02 15:04:05", endStr)
  62. if err != nil {
  63. log.Println("时间段结束时间格式错误", startStr)
  64. continue
  65. }
  66. if startTime.Unix() > endTime.Unix() {
  67. log.Println("开始时间必须小于结束时间", startStr, endStr)
  68. continue
  69. }
  70. if t.After(startTime) && t.Before(endTime) {
  71. return true
  72. }
  73. }
  74. return false
  75. }
  76. func isInWeekOfDay(t time.Time, ta TimeArrow) bool {
  77. nowWeekInt := int(t.Weekday())
  78. for k := range ta.DayOfWeek {
  79. if ta.DayOfWeek[k] == nowWeekInt {
  80. return true
  81. }
  82. }
  83. return false
  84. }
  85. func timeCompletion(a string) string {
  86. sc := strings.Split(a, ":")
  87. for len(sc) < 3 {
  88. sc = append(sc, "00")
  89. }
  90. return strings.Join(sc, ":")
  91. }
  92. func isInDayOfMonth(t time.Time, ta TimeArrow) bool {
  93. day := t.Day()
  94. for e := range ta.DayOfMonth {
  95. if ta.DayOfMonth[e] == day {
  96. return true
  97. }
  98. }
  99. return false
  100. }
  101. func isInTimeOfDay(t time.Time, ta TimeArrow) bool {
  102. if len(ta.TimesOnDay) == 0 {
  103. return true
  104. }
  105. for k := range ta.TimesOnDay {
  106. tsp := strings.Split(ta.TimesOnDay[k], "-")
  107. if len(tsp) < 2 {
  108. log.Println("必须为时间段:", ta.TimesOnDay[k])
  109. continue
  110. }
  111. start, end := tsp[0], tsp[1]
  112. start = timeCompletion(start)
  113. end = timeCompletion(end)
  114. startTime, err := time.Parse("2006-01-02 15:04:05", fmt.Sprintf("%s %s", t.Format("2006-01-02"), start))
  115. if err != nil {
  116. log.Println("时间段开始时间格式错误", start)
  117. continue
  118. }
  119. endTime, err := time.Parse("2006-01-02 15:04:05", fmt.Sprintf("%s %s", t.Format("2006-01-02"), end))
  120. if err != nil {
  121. log.Println("时间段结束时间格式错误", end)
  122. continue
  123. }
  124. if startTime.Unix() > endTime.Unix() {
  125. log.Println("开始时间必须小于结束时间", end)
  126. continue
  127. }
  128. if t.After(startTime) && t.Before(endTime) {
  129. return true
  130. }
  131. }
  132. return false
  133. }
  134. func isInExpandTags(ta TimeArrow, expandTag string) bool {
  135. if len(ta.ExpandTags) == 0 {
  136. return true
  137. }
  138. for e := range ta.ExpandTags {
  139. if ta.ExpandTags[e] == expandTag {
  140. return true
  141. }
  142. }
  143. return false
  144. }
  145. //CreateDayOfWeekTypePlan 创建一个每周计划
  146. func CreateDayOfWeekTypePlan(group string, dayOfWeek []int, timesOnDay []string, expandValue interface{}, expandTags []string, weights float64) TimeArrow {
  147. return TimeArrow{
  148. Type: TimeArrowTypeDayOfWeek,
  149. Group: group,
  150. DayOfWeek: dayOfWeek,
  151. TimesOnDay: timesOnDay,
  152. ExpandValue: expandValue,
  153. ExpandTags: expandTags,
  154. Weights: weights,
  155. }
  156. }
  157. //CreateDayOfMonthTypePlan 创建一个每月计划
  158. func CreateDayOfMonthTypePlan(group string, dayOfMonth []int, timesOnDay []string, expandValue interface{}, expandTags []string, weights float64) TimeArrow {
  159. return TimeArrow{
  160. Type: TimeArrowTypeDayOfMonth,
  161. Group: group,
  162. DayOfMonth: dayOfMonth,
  163. TimesOnDay: timesOnDay,
  164. ExpandValue: expandValue,
  165. ExpandTags: expandTags,
  166. Weights: weights,
  167. }
  168. }
  169. //CreateDateSliceTypePlan 创建一个时间段计划
  170. func CreateDateSliceTypePlan(group string, dateSlice []DateSlice, timesOnDay []string, expandValue interface{}, expandTags []string, weights float64) TimeArrow {
  171. return TimeArrow{
  172. Type: TimeArrowTypeDateSlice,
  173. Group: group,
  174. DateSlice: dateSlice,
  175. TimesOnDay: timesOnDay,
  176. ExpandValue: expandValue,
  177. ExpandTags: expandTags,
  178. Weights: weights,
  179. }
  180. }
  181. func GetHitTimeArrow(t time.Time, group string, expandTags ...string) (*TimeArrow, error) {
  182. ta, err := GetData(group)
  183. if err != nil {
  184. return nil, err
  185. }
  186. sort.Slice(ta, func(i, j int) bool {
  187. return ta[i].Weights > ta[j].Weights
  188. })
  189. for e := range ta {
  190. //当天具体时间判断
  191. if !isInTimeOfDay(t, ta[e]) {
  192. continue
  193. }
  194. //扩展标签判断
  195. if !isInExpandTags(ta[e], strings.Join(expandTags, "-")) {
  196. continue
  197. }
  198. switch ta[e].Type {
  199. case TimeArrowTypeDayOfWeek:
  200. //一周中某一天是否判定
  201. if isInWeekOfDay(t, ta[e]) {
  202. return &ta[e], nil
  203. }
  204. break
  205. case TimeArrowTypeDayOfMonth:
  206. //一月中某一天是否判定
  207. if isInDayOfMonth(t, ta[e]) {
  208. return &ta[e], nil
  209. }
  210. break
  211. case TimeArrowTypeDateSlice:
  212. //一月中某一天是否判定
  213. if isInDateSlice(t, ta[e]) {
  214. return &ta[e], nil
  215. }
  216. break
  217. default:
  218. log.Println("类型错误:", ta[e].Type)
  219. }
  220. }
  221. return nil, nil
  222. }