Files
hunjing/backend/tests/modules/time_sense/test_snapshot.py
T
2026-08-21 16:00:13 +08:00

117 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""时态快照测试。"""
from datetime import UTC, datetime
from app.modules.time_sense.duration import OfflineThresholds
from app.modules.time_sense.snapshot import (
AnniversaryRef,
LocationContext,
SnapshotInput,
compute_snapshot,
)
def _input(**overrides):
base = {
"now": datetime(2026, 7, 3, 2, 42, tzinfo=UTC),
"timezone": "Asia/Shanghai",
"location": LocationContext(timezone="Asia/Shanghai", city="上海"),
"anniversaries": [],
"acquaintance_anchor": datetime(2025, 9, 19, tzinfo=UTC),
"last_active_at": datetime(2026, 7, 3, 2, 0, tzinfo=UTC),
"home_timezone": "Asia/Shanghai",
"offline_thresholds": OfflineThresholds(),
}
base.update(overrides)
return SnapshotInput(**base)
def test_snapshot_basic_fields():
snap = compute_snapshot(_input())
assert snap.timezone == "Asia/Shanghai"
# 上海 UTC+8,02:42 UTC -> 10:42 本地
assert snap.local_hour == 10
assert snap.shichen in {"辰", "巳"} # 7-11 点区间
assert snap.day_period in {"上午"}
assert snap.weekday is not None
def test_snapshot_acquaintance_and_offline():
snap = compute_snapshot(_input())
assert snap.acquaintance.total_days > 280
assert snap.offline.band == "active"
def test_snapshot_home_tz_diff_zero():
snap = compute_snapshot(_input())
assert snap.home_tz_diff_minutes == 0
def test_snapshot_next_milestone_from_anniversary():
# 下一个相识周年:相识日 2025-09-19,到 2026-07-03 距下一周年(2026-09-19)约 78 天
anni = AnniversaryRef(
id="anniv_1",
name="相识纪念日",
calendar="solar",
date_iso="2025-09-19",
recurs_yearly=True,
kind="anniversary",
)
snap = compute_snapshot(_input(anniversaries=[anni]))
assert snap.next_milestone is not None
assert snap.next_milestone.name == "相识纪念日"
assert 70 < snap.next_milestone.days_until < 85
def test_snapshot_active_milestone_today():
# 相识日恰好今天(构造一个今日命中的纪念日)
today = datetime(2026, 7, 3, tzinfo=UTC)
anni = AnniversaryRef(
id="anniv_birthday",
name="小明生日",
calendar="solar",
date_iso="2026-07-03",
recurs_yearly=False,
kind="birthday",
)
snap = compute_snapshot(_input(anniversaries=[anni], acquaintance_anchor=today))
assert any(m.name == "小明生日" for m in snap.active_milestones)
assert snap.next_milestone is None or snap.next_milestone.name != "小明生日"
def test_snapshot_lunar_present():
snap = compute_snapshot(_input())
# 农历字段非空(lunar_python 可用时)
assert snap.lunar is not None
assert snap.lunar.year_ganzhi == "丙午"
def test_snapshot_2_29_anniversary_in_non_leap_year():
# 2/29 周年在非闰年不应崩溃,且应回退到 2/28 后能算出下一周年
anni = AnniversaryRef(
id="anniv_leap",
name="闰年相识",
calendar="solar",
date_iso="2024-02-29",
recurs_yearly=True,
kind="anniversary",
)
snap = compute_snapshot(_input(anniversaries=[anni]))
assert snap.next_milestone is not None
assert snap.next_milestone.name == "闰年相识"
def test_snapshot_recurring_milestone_today():
# recurs_yearly=True 且月日命中今天:应进入 active_milestones
anni = AnniversaryRef(
id="anniv_today",
name="今日周年",
calendar="solar",
date_iso="2026-07-03",
recurs_yearly=True,
kind="anniversary",
)
snap = compute_snapshot(_input(anniversaries=[anni]))
assert any(m.id == "anniv_today" for m in snap.active_milestones)