"""人生时间键与章节排序键(纯函数)。""" from datetime import datetime, timezone from app.agents.memoir.prompts import ( NARRATIVE_MERGE_EXISTING_MAX_CHARS, clip_existing_story_body_for_merge, ) from app.features.story.time_hints import ( infer_story_time_start, life_sort_key_parts, parse_time_start_year, parse_year_from_title, ) def test_parse_year_from_title() -> None: assert parse_year_from_title("1999年 · 小学往事") == 1999 assert parse_year_from_title("2005 · 标题") == 2005 assert parse_year_from_title("无年份标题") is None def test_parse_time_start_year() -> None: assert parse_time_start_year("1999") == 1999 assert parse_time_start_year("1999-03") == 1999 assert parse_time_start_year(None) is None def test_infer_story_time_start_prefers_existing() -> None: assert ( infer_story_time_start( title="2010 · x", canonical_markdown="", existing_time_start="2001", ) == "2001" ) def test_infer_story_time_start_from_title() -> None: assert ( infer_story_time_start( title="2008年 · 某件事", canonical_markdown="正文没有年份", existing_time_start=None, ) == "2008" ) def test_infer_story_time_start_from_body() -> None: assert ( infer_story_time_start( title="无年标题", canonical_markdown="那是2012年的夏天。", existing_time_start=None, ) == "2012" ) def test_clip_existing_story_body_for_merge_truncates() -> None: short = "a" * 100 assert clip_existing_story_body_for_merge(short) == short long = "b" * (NARRATIVE_MERGE_EXISTING_MAX_CHARS + 50) clipped = clip_existing_story_body_for_merge(long) assert "省略" in clipped # 头+尾+提示语可能略长于原串若干字节,但应远小于未截断的线性增长 assert len(clipped) <= len(long) + 400 def test_life_sort_key_parts_order() -> None: t0 = datetime(2020, 1, 1, tzinfo=timezone.utc) t1 = datetime(2021, 1, 1, tzinfo=timezone.utc) a = life_sort_key_parts( time_start="1999", title=None, created_at=t1, story_id="b", ) b = life_sort_key_parts( time_start="2005", title=None, created_at=t0, story_id="a", ) assert a < b