package packagepkg import ( "time" "github.com/break/junhong_cmp_fiber/pkg/constants" ) // CalculateExpiryTime 计算套餐过期时间 // calendarType: 套餐周期类型(natural_month=自然月,by_day=按天) // activatedAt: 激活时间 // durationMonths: 套餐时长(月数,calendar_type=natural_month 时使用) // durationDays: 套餐天数(calendar_type=by_day 时使用) // 返回:过期时间(当天 23:59:59) func CalculateExpiryTime(calendarType string, activatedAt time.Time, durationMonths, durationDays int) time.Time { var expiryDate time.Time if calendarType == constants.PackageCalendarTypeNaturalMonth { // 自然月套餐:activated_at 月份 + N 个月,月末 23:59:59 // 计算目标年月 targetYear := activatedAt.Year() targetMonth := activatedAt.Month() + time.Month(durationMonths) // 处理月份溢出 for targetMonth > 12 { targetMonth -= 12 targetYear++ } // 获取目标月份的最后一天(下个月的第0天就是本月最后一天) expiryDate = time.Date(targetYear, targetMonth+1, 0, 23, 59, 59, 0, activatedAt.Location()) } else { // 按天套餐:activated_at + N 天,23:59:59 expiryDate = activatedAt.AddDate(0, 0, durationDays) expiryDate = time.Date(expiryDate.Year(), expiryDate.Month(), expiryDate.Day(), 23, 59, 59, 0, expiryDate.Location()) } return expiryDate } // CalculateNextResetTime 计算下次流量重置时间 // dataResetCycle: 流量重置周期(daily/monthly/yearly/none) // currentTime: 当前时间 // billingDay: 计费日(月重置时使用,联通=27,其他=1) // 返回:下次重置时间(00:00:00) func CalculateNextResetTime(dataResetCycle string, currentTime time.Time, billingDay int) *time.Time { if dataResetCycle == constants.PackageDataResetNone { // 不重置 return nil } var nextResetTime time.Time switch dataResetCycle { case constants.PackageDataResetDaily: // 日重置:明天 00:00:00 nextResetTime = time.Date( currentTime.Year(), currentTime.Month(), currentTime.Day()+1, 0, 0, 0, 0, currentTime.Location(), ) case constants.PackageDataResetMonthly: // 月重置:下月 billingDay 号 00:00:00 year := currentTime.Year() month := currentTime.Month() // 检查 billingDay 是否为当前月的最后一天(月末计费的特殊情况) currentMonthLastDay := time.Date(year, month+1, 0, 0, 0, 0, 0, currentTime.Location()).Day() isBillingDayMonthEnd := billingDay >= currentMonthLastDay // 如果当前日期 >= billingDay,则重置时间为下个月的 billingDay // 否则,重置时间为本月的 billingDay // 特殊情况:如果 billingDay 是月末,并且当前日期已接近月末,则跳到下个月 shouldUseNextMonth := currentTime.Day() >= billingDay || (isBillingDayMonthEnd && currentTime.Day() >= currentMonthLastDay-1) if shouldUseNextMonth { // 下个月 month++ if month > 12 { month = 1 year++ } } // 计算目标月份的最后一天(处理月末情况) lastDayOfMonth := time.Date(year, month+1, 0, 0, 0, 0, 0, currentTime.Location()).Day() resetDay := billingDay if billingDay > lastDayOfMonth { // 如果 billingDay 超过该月天数,使用月末 resetDay = lastDayOfMonth } nextResetTime = time.Date(year, month, resetDay, 0, 0, 0, 0, currentTime.Location()) case constants.PackageDataResetYearly: // 年重置:明年 1 月 1 日 00:00:00 nextResetTime = time.Date( currentTime.Year()+1, 1, 1, 0, 0, 0, 0, currentTime.Location(), ) default: return nil } return &nextResetTime }