// Copyright 2026 tamakyi. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package report import ( "testing" "time" "github.com/stretchr/testify/require" ) // TestPreviousWeek 覆盖周报窗口:[周一 00:00, 下周一 00:00),且与「现在是周几」无关。 func TestPreviousWeek(t *testing.T) { loc := time.Local cases := []struct { name string now time.Time wantStart time.Time wantEnd time.Time }{ { name: "周一凌晨(报告应在此时发出,覆盖上周)", now: time.Date(2026, 10, 26, 1, 0, 0, 0, loc), // 周一 wantStart: time.Date(2026, 10, 19, 0, 0, 0, 0, loc), wantEnd: time.Date(2026, 10, 26, 0, 0, 0, 0, loc), }, { name: "周三补发:仍然覆盖「上周」而不是本周至今", now: time.Date(2026, 10, 28, 15, 30, 0, 0, loc), // 周三 wantStart: time.Date(2026, 10, 19, 0, 0, 0, 0, loc), wantEnd: time.Date(2026, 10, 26, 0, 0, 0, 0, loc), }, { name: "周日晚间:还没到本周结束,仍覆盖上周", now: time.Date(2026, 10, 25, 23, 59, 0, 0, loc), // 周日 wantStart: time.Date(2026, 10, 12, 0, 0, 0, 0, loc), wantEnd: time.Date(2026, 10, 19, 0, 0, 0, 0, loc), }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { p := PreviousWeek(c.now) require.Equal(t, c.wantStart, p.Start) require.Equal(t, c.wantEnd, p.End) // 窗口必须正好 7 天,且左闭右开 require.Equal(t, 7*24*time.Hour, p.End.Sub(p.Start)) }) } } // TestPreviousWeekKey 覆盖 ISO 周号,特别是跨年那一周。 func TestPreviousWeekKey(t *testing.T) { loc := time.Local // 2027-01-01 是周五,属于 ISO 2026 年第 53 周; // 2026-12-28(周一)~ 2027-01-03(周日)正是这一周。 // 若用 end 去算周号会得到 2027-W01,导致这一周的台账键错位。 p := PreviousWeek(time.Date(2027, 1, 4, 9, 0, 0, 0, loc)) // 周一 require.Equal(t, "week:2026-W53", p.Key) require.Equal(t, time.Date(2026, 12, 28, 0, 0, 0, 0, loc), p.Start) // 跨年另一侧:2026-01-01 所在周是 2026-W01,前一周属于 2025-W52。 p2 := PreviousWeek(time.Date(2026, 1, 5, 9, 0, 0, 0, loc)) require.Equal(t, "week:2026-W01", p2.Key) } // TestPreviousMonth 覆盖月报窗口,含 31 天/30 天/2 月。 func TestPreviousMonth(t *testing.T) { loc := time.Local p := PreviousMonth(time.Date(2026, 11, 3, 10, 0, 0, 0, loc)) require.Equal(t, "month:2026-10", p.Key) require.Equal(t, time.Date(2026, 10, 1, 0, 0, 0, 0, loc), p.Start) require.Equal(t, time.Date(2026, 11, 1, 0, 0, 0, 0, loc), p.End) // 闰年 2 月必须有 29 天,且不能因为「减一个月」跑到 3 月去。 p2 := PreviousMonth(time.Date(2024, 3, 1, 0, 30, 0, 0, loc)) require.Equal(t, "month:2024-02", p2.Key) require.Equal(t, time.Date(2024, 2, 1, 0, 0, 0, 0, loc), p2.Start) require.Equal(t, 29*24*time.Hour, p2.End.Sub(p2.Start)) // 5 月 31 日往前一个月不能变成「4 月 31 日」这种不存在的日期: // 窗口是 [4-01, 5-01),不需要做任何日期加减。 p3 := PreviousMonth(time.Date(2026, 5, 31, 12, 0, 0, 0, loc)) require.Equal(t, time.Date(2026, 4, 1, 0, 0, 0, 0, loc), p3.Start) require.Equal(t, time.Date(2026, 5, 1, 0, 0, 0, 0, loc), p3.End) } // TestPeriodLabel 覆盖展示用的窗口描述:右端点要退一天,别让人以为多算了一天。 func TestPeriodLabel(t *testing.T) { loc := time.Local p := PreviousWeek(time.Date(2026, 10, 26, 1, 0, 0, 0, loc)) require.Equal(t, "2026-10-19 ~ 2026-10-25", p.Label()) m := PreviousMonth(time.Date(2026, 11, 3, 10, 0, 0, 0, loc)) require.Equal(t, "2026-10", m.Label()) require.Equal(t, "security-month-2026-10", m.Filename()) }