Merge pull request #6089 from lyen1688/feat/channel-time-pricing-weekdays

新增渠道时间段定价工作日生效规则
This commit is contained in:
Wesley Liddick
2026-08-24 10:21:47 +08:00
committed by GitHub
13 changed files with 149 additions and 31 deletions
+7 -3
View File
@@ -109,8 +109,9 @@ type ChannelModelPricing struct {
// ChannelTimePricing 渠道模型定价的分时倍率配置。
type ChannelTimePricing struct {
Timezone string `json:"timezone"`
Periods []ChannelTimePricingPeriod `json:"periods"`
Timezone string `json:"timezone"`
WeekdaysOnly bool `json:"weekdays_only,omitempty"`
Periods []ChannelTimePricingPeriod `json:"periods"`
}
// ChannelTimePricingPeriod 是秒级的左闭右开分时倍率区间,并兼容历史 HH:mm 数据。
@@ -216,7 +217,10 @@ func (p ChannelModelPricing) Clone() ChannelModelPricing {
copy(cp.Intervals, p.Intervals)
}
if p.TimePricing != nil {
cp.TimePricing = &ChannelTimePricing{Timezone: p.TimePricing.Timezone}
cp.TimePricing = &ChannelTimePricing{
Timezone: p.TimePricing.Timezone,
WeekdaysOnly: p.TimePricing.WeekdaysOnly,
}
if p.TimePricing.Periods != nil {
cp.TimePricing.Periods = append([]ChannelTimePricingPeriod(nil), p.TimePricing.Periods...)
}
+4 -1
View File
@@ -198,7 +198,8 @@ func TestChannelModelPricingClone(t *testing.T) {
{MinTokens: 0, TierLabel: "tier1"},
},
TimePricing: &ChannelTimePricing{
Timezone: "Asia/Shanghai",
Timezone: "Asia/Shanghai",
WeekdaysOnly: true,
Periods: []ChannelTimePricingPeriod{{
StartTime: "09:00",
EndTime: "12:00",
@@ -217,9 +218,11 @@ func TestChannelModelPricingClone(t *testing.T) {
require.Equal(t, "tier1", original.Intervals[0].TierLabel)
cloned.TimePricing.Timezone = "America/New_York"
cloned.TimePricing.WeekdaysOnly = false
cloned.TimePricing.Periods[0].StartTime = "10:00"
cloned.TimePricing.Periods[0].Multiplier = 3
require.Equal(t, "Asia/Shanghai", original.TimePricing.Timezone)
require.True(t, original.TimePricing.WeekdaysOnly)
require.Equal(t, "09:00", original.TimePricing.Periods[0].StartTime)
require.Equal(t, 2.0, original.TimePricing.Periods[0].Multiplier)
}
@@ -47,6 +47,9 @@ func (config *ChannelTimePricing) MultiplierAt(at time.Time) float64 {
}
local := at.In(location)
if config.WeekdaysOnly && (local.Weekday() == time.Saturday || local.Weekday() == time.Sunday) {
return 1.0
}
second := local.Hour()*60*60 + local.Minute()*60 + local.Second()
for _, period := range periods {
if second >= period.start && second < period.end {
@@ -95,6 +95,30 @@ func TestChannelTimePricingMultiplierAt(t *testing.T) {
require.Equal(t, 2.0, newYork.MultiplierAt(at))
}
func TestChannelTimePricingMultiplierAtWeekdaysOnly(t *testing.T) {
config := &ChannelTimePricing{
Timezone: "Asia/Shanghai",
WeekdaysOnly: true,
Periods: onePeriod(),
}
tests := []struct {
name string
at time.Time
want float64
}{
{name: "Monday in configured timezone", at: time.Date(2026, 6, 29, 1, 0, 0, 0, time.UTC), want: 2},
{name: "Saturday in configured timezone", at: time.Date(2026, 7, 4, 1, 0, 0, 0, time.UTC), want: 1},
{name: "Sunday in configured timezone", at: time.Date(2026, 7, 5, 1, 0, 0, 0, time.UTC), want: 1},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.want, config.MultiplierAt(tt.at))
})
}
}
func TestChannelTimePricingMultiplierAtSecondPrecision(t *testing.T) {
config := timeConfig(ChannelTimePricingPeriod{StartTime: "09:00:30", EndTime: "09:00:45", Multiplier: 2})
shanghai, err := time.LoadLocation("Asia/Shanghai")