package utils import ( "errors" "fmt" "time" ) const PeriodNoFormatLayout = "2006010215" // NowPeriodNo 当前期编号 -- 偶数小时 func NowPeriodNo() string { now := time.Now() // 获取当前小时 currentHour := now.Hour() // 计算偶数小时 var evenHour int if currentHour%2 == 0 { // 如果当前小时已经是偶数小时,使用当前小时 evenHour = currentHour } else { // 如果当前是奇数小时,使用上一个偶数小时 evenHour = currentHour - 1 } // 创建期号时间 periodTime := time.Date( now.Year(), now.Month(), now.Day(), evenHour, 0, 0, 0, now.Location(), ) return periodTime.Format(PeriodNoFormatLayout) } // NextPeriodNo 下一期编号 func NextPeriodNo(periodNo string) (string, error) { return JumpToPeriodNo(periodNo, 1) } // JumpToPeriodNo 根据传入期号计算相隔N期期号 func JumpToPeriodNo(periodNo string, n uint64) (string, error) { // 验证期号长度 if len(periodNo) != len(PeriodNoFormatLayout) { return "", errors.New("invalid period number format") } // 解析期号为时间 periodTime, err := time.Parse(PeriodNoFormatLayout, periodNo) if err != nil { return "", fmt.Errorf("parse period number failed: %w", err) } // 验证小时是否为偶数(可选) hour := periodTime.Hour() if hour%2 != 0 { return "", errors.New("hour must be even number") } // 计算N个2小时的时间间隔 duration := time.Duration(n*2) * time.Hour // 计算目标时间 targetTime := periodTime.Add(duration) return targetTime.Format(PeriodNoFormatLayout), nil } // 为保持与原始接口一致,提供简化版本 func NextPeriodNoSimple(periodNo string) string { result, err := NextPeriodNo(periodNo) if err != nil { return "" } return result } func JumpToPeriodNoSimple(periodNo string, n uint64) string { result, err := JumpToPeriodNo(periodNo, n) if err != nil { return "" } return result } // CalPeriodNosSpan 计算两期之间跨度 // 返回从 beginPeriodNo 到 endPeriodNo 相差的期数 // 如果 endPeriodNo 在 beginPeriodNo 之后,返回正数 // 如果 endPeriodNo 在 beginPeriodNo 之前,返回负数 // 如果期号格式错误,返回0 func CalPeriodNosSpan(beginPeriodNo, endPeriodNo string) int { // 解析期号为时间 beginTime, err := time.Parse(PeriodNoFormatLayout, beginPeriodNo) if err != nil { return 0 } endTime, err := time.Parse(PeriodNoFormatLayout, endPeriodNo) if err != nil { return 0 } // 计算时间差(以小时为单位) duration := endTime.Sub(beginTime) hours := int(duration.Hours()) // 将小时差转换为期数差(2小时为一期) // 注意:如果 hours 不是2的倍数,说明期号不是偶数小时,但我们仍然计算整数期数 periods := hours / 2 return periods }