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.
 
 
 
 
 
 

63 lines
2.2 KiB

package utils
import (
"testing"
"time"
)
// 验证按固定时区跨 0 点归日:同一 UTC 时刻在中国时区(UTC+8)下归到正确的统计日。
func TestStatDayNumber_Timezone(t *testing.T) {
loc := LoadStatLocation("Asia/Shanghai")
cases := []struct {
utc time.Time
want uint32
}{
// 16:30 UTC = 次日 00:30 CST → 归到次日
{time.Date(2026, 6, 17, 16, 30, 0, 0, time.UTC), 20260618},
// 15:30 UTC = 当日 23:30 CST → 仍归当日
{time.Date(2026, 6, 17, 15, 30, 0, 0, time.UTC), 20260617},
// 跨月:05-31 16:00 UTC = 06-01 00:00 CST
{time.Date(2026, 5, 31, 16, 0, 0, 0, time.UTC), 20260601},
// 跨年:12-31 16:00 UTC = 次年 01-01 00:00 CST
{time.Date(2026, 12, 31, 16, 0, 0, 0, time.UTC), 20270101},
}
for _, c := range cases {
if got := StatDayNumber(c.utc, loc); got != c.want {
t.Fatalf("StatDayNumber(%s, CST)=%d, want %d", c.utc.Format(time.RFC3339), got, c.want)
}
}
}
// 验证 YYYYMMDD 的数值序与日期时序一致(cleanup「statDay < yesterday」依赖此性质)。
func TestStatDayNumber_MonotonicAcrossBoundaries(t *testing.T) {
loc := LoadStatLocation("Asia/Shanghai")
day := func(y, m, d int) uint32 {
return StatDayNumber(time.Date(y, time.Month(m), d, 12, 0, 0, 0, time.UTC), loc)
}
if !(day(2026, 1, 31) < day(2026, 2, 1)) {
t.Fatal("跨月序错误:20260131 应 < 20260201")
}
if !(day(2025, 12, 31) < day(2026, 1, 1)) {
t.Fatal("跨年序错误:20251231 应 < 20260101")
}
}
// Asia/Shanghai 全年偏移恒为 +8h(无夏令时),fallback 到 FixedZone 也应等价。
func TestLoadStatLocation_OffsetIsPlus8(t *testing.T) {
loc := LoadStatLocation("Asia/Shanghai")
for _, mth := range []int{1, 6, 12} {
_, off := time.Date(2026, time.Month(mth), 15, 12, 0, 0, 0, loc).Zone()
if off != 8*3600 {
t.Fatalf("Asia/Shanghai 月份%d 偏移应为 +8h, got %ds", mth, off)
}
}
}
// 到下一个 0 点的间隔应在 (0, 24h+5s] 内,且带 +5s 缓冲。
func TestDurationToNextMidnight_Range(t *testing.T) {
loc := LoadStatLocation("Asia/Shanghai")
d := DurationToNextMidnight(loc)
if d <= 0 || d > 24*time.Hour+5*time.Second {
t.Fatalf("DurationToNextMidnight 越界: %s", d)
}
}