time_period.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package utils
  2. import (
  3. "errors"
  4. "fmt"
  5. "time"
  6. )
  7. const PeriodNoFormatLayout = "2006010215"
  8. // NowPeriodNo 当前期编号 -- 偶数小时
  9. func NowPeriodNo() string {
  10. now := time.Now()
  11. // 获取当前小时
  12. currentHour := now.Hour()
  13. // 计算偶数小时
  14. var evenHour int
  15. if currentHour%2 == 0 {
  16. // 如果当前小时已经是偶数小时,使用当前小时
  17. evenHour = currentHour
  18. } else {
  19. // 如果当前是奇数小时,使用上一个偶数小时
  20. evenHour = currentHour - 1
  21. }
  22. // 创建期号时间
  23. periodTime := time.Date(
  24. now.Year(),
  25. now.Month(),
  26. now.Day(),
  27. evenHour,
  28. 0, 0, 0,
  29. now.Location(),
  30. )
  31. return periodTime.Format(PeriodNoFormatLayout)
  32. }
  33. // NextPeriodNo 下一期编号
  34. func NextPeriodNo(periodNo string) (string, error) {
  35. return JumpToPeriodNo(periodNo, 1)
  36. }
  37. // JumpToPeriodNo 根据传入期号计算相隔N期期号
  38. func JumpToPeriodNo(periodNo string, n uint64) (string, error) {
  39. // 验证期号长度
  40. if len(periodNo) != len(PeriodNoFormatLayout) {
  41. return "", errors.New("invalid period number format")
  42. }
  43. // 解析期号为时间
  44. periodTime, err := time.Parse(PeriodNoFormatLayout, periodNo)
  45. if err != nil {
  46. return "", fmt.Errorf("parse period number failed: %w", err)
  47. }
  48. // 验证小时是否为偶数(可选)
  49. hour := periodTime.Hour()
  50. if hour%2 != 0 {
  51. return "", errors.New("hour must be even number")
  52. }
  53. // 计算N个2小时的时间间隔
  54. duration := time.Duration(n*2) * time.Hour
  55. // 计算目标时间
  56. targetTime := periodTime.Add(duration)
  57. return targetTime.Format(PeriodNoFormatLayout), nil
  58. }
  59. // 为保持与原始接口一致,提供简化版本
  60. func NextPeriodNoSimple(periodNo string) string {
  61. result, err := NextPeriodNo(periodNo)
  62. if err != nil {
  63. return ""
  64. }
  65. return result
  66. }
  67. func JumpToPeriodNoSimple(periodNo string, n uint64) string {
  68. result, err := JumpToPeriodNo(periodNo, n)
  69. if err != nil {
  70. return ""
  71. }
  72. return result
  73. }
  74. // CalPeriodNosSpan 计算两期之间跨度
  75. // 返回从 beginPeriodNo 到 endPeriodNo 相差的期数
  76. // 如果 endPeriodNo 在 beginPeriodNo 之后,返回正数
  77. // 如果 endPeriodNo 在 beginPeriodNo 之前,返回负数
  78. // 如果期号格式错误,返回0
  79. func CalPeriodNosSpan(beginPeriodNo, endPeriodNo string) int {
  80. // 解析期号为时间
  81. beginTime, err := time.Parse(PeriodNoFormatLayout, beginPeriodNo)
  82. if err != nil {
  83. return 0
  84. }
  85. endTime, err := time.Parse(PeriodNoFormatLayout, endPeriodNo)
  86. if err != nil {
  87. return 0
  88. }
  89. // 计算时间差(以小时为单位)
  90. duration := endTime.Sub(beginTime)
  91. hours := int(duration.Hours())
  92. // 将小时差转换为期数差(2小时为一期)
  93. // 注意:如果 hours 不是2的倍数,说明期号不是偶数小时,但我们仍然计算整数期数
  94. periods := hours / 2
  95. return periods
  96. }