时间选定库
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.

359 lines
9.1 KiB

5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
  1. package time_arrow
  2. import (
  3. "fmt"
  4. "github.com/google/uuid"
  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. TimeArrowTypeInHolidays TimeArrowType = "IN_HOLIDAYS" //节假日
  16. TimeArrowTypeAtLastDayHolidays TimeArrowType = "AT_LAST_DAY_HOLIDAYS" //节假日最后一天
  17. TimeArrowTypePriorToDayHolidays TimeArrowType = "PRIOR_TO_DAY_HOLIDAYS" //节假日前一天
  18. )
  19. type DateSlice struct {
  20. Start string `json:"start"`
  21. End string `json:"end"`
  22. }
  23. type TimeArrow struct {
  24. TimeArrowId string `json:"time_arrow_id"`
  25. Group string `json:"group"`
  26. Type TimeArrowType `json:"type"`
  27. //可选
  28. DayOfWeek []int `json:"day_of_week"`
  29. DayOfMonth []int `json:"day_of_month"`
  30. DateSlice []DateSlice `json:"date_slice"`
  31. //必选
  32. TimesOnDay []string `json:"times_on_day"`
  33. ExpandTags []string `json:"expand_tags"`
  34. ExpandValue interface{} `json:"expand_value"`
  35. Weights float64 `json:"weights"`
  36. Extension map[string]interface{} `json:"extension"`
  37. }
  38. type TimeArrows []TimeArrow
  39. func isInDateSlice(t time.Time, ta TimeArrow) bool {
  40. for e := range ta.DateSlice {
  41. startStr := ta.DateSlice[e].Start
  42. startSc := strings.Split(startStr, " ")
  43. if len(startSc) < 2 {
  44. startSc = append(startSc, "00:00:00")
  45. } else {
  46. startSc[1] = timeCompletion(startSc[1])
  47. }
  48. startStr = strings.Join(startSc, " ")
  49. endStr := ta.DateSlice[e].End
  50. endSc := strings.Split(endStr, " ")
  51. if len(endSc) < 2 {
  52. endSc = append(endSc, "00:00:00")
  53. } else {
  54. endSc[1] = timeCompletion(endSc[1])
  55. }
  56. endStr = strings.Join(endSc, " ")
  57. startTime, err := time.ParseInLocation("2006-01-02 15:04:05", startStr, time.Local)
  58. if err != nil {
  59. log.Println("时间段开始时间格式错误", startStr)
  60. continue
  61. }
  62. endTime, err := time.ParseInLocation("2006-01-02 15:04:05", endStr, time.Local)
  63. if err != nil {
  64. log.Println("时间段结束时间格式错误", startStr)
  65. continue
  66. }
  67. if startTime.Unix() > endTime.Unix() {
  68. log.Println("开始时间必须小于结束时间", startStr, endStr)
  69. continue
  70. }
  71. if (t.After(startTime) || t.Equal(startTime)) && t.Before(endTime) {
  72. return true
  73. }
  74. }
  75. return false
  76. }
  77. func isInWeekOfDay(t time.Time, ta TimeArrow) bool {
  78. nowWeekInt := int(t.Weekday())
  79. for k := range ta.DayOfWeek {
  80. if ta.DayOfWeek[k] == nowWeekInt {
  81. return true
  82. }
  83. }
  84. return false
  85. }
  86. func timeCompletion(a string) string {
  87. sc := strings.Split(a, ":")
  88. for len(sc) < 3 {
  89. sc = append(sc, "00")
  90. }
  91. return strings.Join(sc, ":")
  92. }
  93. func isInDayOfMonth(t time.Time, ta TimeArrow) bool {
  94. day := t.Day()
  95. for e := range ta.DayOfMonth {
  96. if ta.DayOfMonth[e] == day {
  97. return true
  98. }
  99. }
  100. return false
  101. }
  102. func isInTimeOfDay(t time.Time, ta TimeArrow) bool {
  103. if len(ta.TimesOnDay) == 0 {
  104. return true
  105. }
  106. for k := range ta.TimesOnDay {
  107. tsp := strings.Split(ta.TimesOnDay[k], "-")
  108. if len(tsp) < 2 {
  109. log.Println("必须为时间段:", ta.TimesOnDay[k])
  110. continue
  111. }
  112. start, end := tsp[0], tsp[1]
  113. start = timeCompletion(start)
  114. end = timeCompletion(end)
  115. startTime, err := time.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%s %s", t.Format("2006-01-02"), start), time.Local)
  116. if err != nil {
  117. log.Println("时间段开始时间格式错误", start)
  118. continue
  119. }
  120. if end == "24" || end == "24:00" || end == "24:00:00" {
  121. end = "23:59:59"
  122. }
  123. endTime, err := time.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%s %s", t.Format("2006-01-02"), end), time.Local)
  124. if err != nil {
  125. log.Println("时间段结束时间格式错误", end)
  126. continue
  127. }
  128. if startTime.Unix() > endTime.Unix() {
  129. log.Println("开始时间必须小于结束时间", end)
  130. continue
  131. }
  132. if (t.After(startTime) || t.Equal(startTime)) && t.Before(endTime) {
  133. return true
  134. }
  135. }
  136. return false
  137. }
  138. func isInHolidays(t time.Time) bool {
  139. holidaysData, err := GetHolidaysData()
  140. if err != nil {
  141. return false
  142. }
  143. for e := range holidaysData {
  144. startTime := holidaysData[e].Start.Local()
  145. endTime := holidaysData[e].End.Local()
  146. if (t.After(startTime) || t.Equal(startTime)) && t.Before(endTime) {
  147. return true
  148. }
  149. }
  150. return false
  151. }
  152. func isInAtLastDayHolidays(t time.Time) bool {
  153. t = t.Local()
  154. holidaysData, err := GetHolidaysData()
  155. if err != nil {
  156. return false
  157. }
  158. for e := range holidaysData {
  159. startTime, err := time.ParseInLocation("2006-01-02 15:04:05", holidaysData[e].End.Format("2006-01-02 00:00:00"), time.Local)
  160. if err != nil {
  161. log.Println("节假日最后一天时间段开始时间格式错误", holidaysData[e].End)
  162. continue
  163. }
  164. endTime, err := time.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%s 23:59:59", holidaysData[e].End.Format("2006-01-02")), time.Local)
  165. if err != nil {
  166. log.Println("节假日最后一天时间段结束时间格式错误", holidaysData[e].End)
  167. continue
  168. }
  169. if (t.After(startTime) || t.Equal(startTime)) && t.Before(endTime) {
  170. return true
  171. }
  172. }
  173. return false
  174. }
  175. func isInPriorToDayHolidays(t time.Time) bool {
  176. holidaysData, err := GetHolidaysData()
  177. if err != nil {
  178. return false
  179. }
  180. for e := range holidaysData {
  181. startTime, err := time.ParseInLocation("2006-01-02 15:04:05", holidaysData[e].Start.AddDate(0, 0, -1).Format("2006-01-02 00:00:00"), time.Local)
  182. if err != nil {
  183. log.Println("节假日前一天时间段开始时间格式错误", holidaysData[e].Start)
  184. continue
  185. }
  186. endTime, err := time.ParseInLocation("2006-01-02 15:04:05", fmt.Sprintf("%s 23:59:59", holidaysData[e].Start.AddDate(0, 0, -1).Format("2006-01-02")), time.Local)
  187. if err != nil {
  188. log.Println("节假日前一天时间段结束时间格式错误", holidaysData[e].Start)
  189. continue
  190. }
  191. if (t.After(startTime) || t.Equal(startTime)) && t.Before(endTime) {
  192. return true
  193. }
  194. }
  195. return false
  196. }
  197. func isInExpandTags(ta TimeArrow, expandTag string) bool {
  198. if len(ta.ExpandTags) == 0 {
  199. return true
  200. }
  201. for e := range ta.ExpandTags {
  202. if ta.ExpandTags[e] == expandTag {
  203. return true
  204. }
  205. }
  206. return false
  207. }
  208. func createUUID() string {
  209. uid := uuid.Must(uuid.NewUUID())
  210. return uid.String()
  211. }
  212. //CreateDayOfWeekTypePlan 创建一个每周计划
  213. func CreateDayOfWeekTypePlan(group string, dayOfWeek []int, timesOnDay []string, expandValue interface{}, expandTags []string, weights float64) TimeArrow {
  214. return TimeArrow{
  215. TimeArrowId: createUUID(),
  216. Type: TimeArrowTypeDayOfWeek,
  217. Group: group,
  218. DayOfWeek: dayOfWeek,
  219. TimesOnDay: timesOnDay,
  220. ExpandValue: expandValue,
  221. ExpandTags: expandTags,
  222. Weights: weights,
  223. }
  224. }
  225. //CreateDayOfMonthTypePlan 创建一个每月计划
  226. func CreateDayOfMonthTypePlan(group string, dayOfMonth []int, timesOnDay []string, expandValue interface{}, expandTags []string, weights float64) TimeArrow {
  227. return TimeArrow{
  228. TimeArrowId: createUUID(),
  229. Type: TimeArrowTypeDayOfMonth,
  230. Group: group,
  231. DayOfMonth: dayOfMonth,
  232. TimesOnDay: timesOnDay,
  233. ExpandValue: expandValue,
  234. ExpandTags: expandTags,
  235. Weights: weights,
  236. }
  237. }
  238. //CreateDateSliceTypePlan 创建一个时间段计划
  239. func CreateDateSliceTypePlan(group string, dateSlice []DateSlice, timesOnDay []string, expandValue interface{}, expandTags []string, weights float64) TimeArrow {
  240. return TimeArrow{
  241. TimeArrowId: createUUID(),
  242. Type: TimeArrowTypeDateSlice,
  243. Group: group,
  244. DateSlice: dateSlice,
  245. TimesOnDay: timesOnDay,
  246. ExpandValue: expandValue,
  247. ExpandTags: expandTags,
  248. Weights: weights,
  249. }
  250. }
  251. type HolidaysItem struct {
  252. Name string `json:"name"`
  253. Start time.Time `json:"start"`
  254. End time.Time `json:"end"`
  255. }
  256. var GetHolidaysData func() ([]HolidaysItem, error)
  257. type TimeArrowHelper struct {
  258. GetData func(group string) (TimeArrows, error)
  259. }
  260. func (th *TimeArrowHelper) GetHitTimeArrow(t time.Time, group string, expandTags ...string) (*TimeArrow, error) {
  261. ta, err := th.GetData(group)
  262. if err != nil {
  263. return nil, err
  264. }
  265. sort.Slice(ta, func(i, j int) bool {
  266. return ta[i].Weights > ta[j].Weights
  267. })
  268. for e := range ta {
  269. //当天具体时间判断
  270. if !isInTimeOfDay(t, ta[e]) {
  271. continue
  272. }
  273. //扩展标签判断
  274. if !isInExpandTags(ta[e], strings.Join(expandTags, "-")) {
  275. continue
  276. }
  277. switch ta[e].Type {
  278. case TimeArrowTypeDayOfWeek:
  279. //一周中某一天是否判定
  280. if isInWeekOfDay(t, ta[e]) {
  281. return &ta[e], nil
  282. }
  283. break
  284. case TimeArrowTypeDayOfMonth:
  285. //一月中某一天是否判定
  286. if isInDayOfMonth(t, ta[e]) {
  287. return &ta[e], nil
  288. }
  289. break
  290. case TimeArrowTypeDateSlice:
  291. //一月中某一天是否判定
  292. if isInDateSlice(t, ta[e]) {
  293. return &ta[e], nil
  294. }
  295. break
  296. case TimeArrowTypeAtLastDayHolidays:
  297. //节假日最后一天
  298. if isInAtLastDayHolidays(t) {
  299. return &ta[e], nil
  300. }
  301. break
  302. case TimeArrowTypePriorToDayHolidays:
  303. //节假日前一天
  304. if isInPriorToDayHolidays(t) {
  305. return &ta[e], nil
  306. }
  307. break
  308. case TimeArrowTypeInHolidays:
  309. //节假日
  310. if isInHolidays(t) {
  311. return &ta[e], nil
  312. }
  313. break
  314. default:
  315. log.Println("类型错误:", ta[e].Type)
  316. }
  317. }
  318. return nil, nil
  319. }