feat(upload): date detection reads filename first, body falls back (#610) by rollroyces · Pull Request #979 · deeplethe/utopia · GitHub
Skip to content

feat(upload): date detection reads filename first, body falls back (#610) - #979

Merged
WaylandYang merged 3 commits into
deeplethe:devfrom
rollroyces:feat/upload-filename-date-detection
Sep 27, 2026
Merged

WaylandYang merged 3 commits into
deeplethe:devfrom
rollroyces:feat/upload-filename-date-detection

Conversation

@rollroyces

Copy link
Copy Markdown
Contributor

Closes #610.

公告、备案语料通常按日期命名,multipart 时这信息已经在文件名里了

文件层面解析日期的顺序之前只看正文首行:(2024-02-29)、2024年2月29日 之类的。但公告/备案一类的语料通常按日期命名 — 文件叫 2024-02-29_filing.txt,而正文里写的可能是上下文 — 对读的人来说文件名上的日期和正文里写「2024年2月29日 公告」这两件事指的是同一个日期。

维护者在 #610 已经拍板:content_time 要先看文件名,没认出来再看正文。这一档:

  • ISO YYYY-MM-DD 或中文 YYYY年M月D日,主名开头即匹配
  • 月/日 1-2 位都行(与正文解析路径一致;输出一律标准化为 2 位)
  • 与正文解析共用同一套拒收规则:chrono 拒闰年错月之类,partial / ambiguous / impossible 全 None
  • 只对 text extension(txt / md / markdown)开 — PDF/Word 的日期走各自解析器读元数据,文件层面的格式识别不在这里做

落库契约不变

doc_time_source = "content" 还是由 content_time 的 Some(_) 决定 — 这条已经在 #714 + 0064 那里接好了,不动它。集成测试加了一条:ISO 文件名 + 正文无日期、中文文件名、ISO 文件名 + 中文正文,三种都走文件名解析,落到 DB 之后 doc_time 与 doc_time_source 都对得上。

前端:文档日期与上传时刻分两段显示

之前 DocViewer 头只显示 created_at(上传时刻),把「文档日期」这件事完全藏起来。维护者决定 5:上传时刻和文档日期必须分开 — 否则跨时区归档时看文档的人会把上传时间当成文档时间。

  • Doc 类型补 doc_time: string | null 与 doc_time_source: "content" | "none"
  • DocViewer 头:段数 · 大小 · 文档日期 · 上传时刻
  • i18n(en/zh)补 docDate / docDateFromContent / uploadedAt 字符串

文件清单

  • crates/utopia-server/src/api/documents_routes.rs:content_time 加 is_text_extension + parse_filename_date 两层 helper,文件名先解析;正文兜底
  • crates/utopia-server/src/api/documents_routes_tests.rs:4 条单测覆盖文件名 ISO / 中文 / fallback / partial / ambiguous / leap-year 边界;1 条连库测试覆盖 ISO 文件名 + 中文文件名 + ISO 文件名 + 中文正文
  • web/src/api.ts:Doc 接口补 doc_time 与 doc_time_source
  • web/src/pages/DocViewer.tsx:抽 DocMeta 组件,文档日期与上传时刻分两段显示
  • web/src/i18n/{en,zh}.ts:补 docDate / docDateFromContent / uploadedAt

测试

  • cargo test --package utopia-server --bin utopia-server — 493 passed(+1:新增 a_filename_with_a_date_drives_doc_time_when_body_has_none 集成测试在没有 DB 时跳过,与项目约定一致)
  • cargo test --package utopia-server --bin utopia-server 'a_filename_with_a_leading_date_sets_the_date_even_when_body_has_none' 等 4 条新单测全过
  • pnpm exec tsc --noEmit — 0 errors
  • pnpm test — 23 files / 196 tests passed
  • cargo clippy --package utopia-server --all-targets -- -D warnings — clean
  • cargo fmt --check — clean

后续

库列表页(Library.tsx)目前还没改 — 那是另一个面板,按维护者决定的「分开显示」要求,这次只动文档查看器。后续可以照同一套形态铺过去。

rollroyces and others added 2 commits September 27, 2026 19:35
…eeplethe#610)

公告、备案一类的语料通常按日期命名;multipart 解析的时候这个
日期已经在文件名里了,不必再去正文里猜。读法顺序变成:
文件名 → 正文首行,与正文那一档格式一致(ISO 或中文全形)。

- content_time 先看主名开头是不是一个完整日期,是的话拿它走;
  否则再走正文的(原来那一档)解析
- 主名解析与正文解析共用同一套拒收规则(chrono 拒闰年错月
  之类),所以 partial / ambiguous / impossible 的输入照旧全 None
- 文件名解析只对 text extension(txt/md/markdown)开,PDF / Word
  的日期走各自解析器读元数据,文件层面的格式识别不在这里做

落库后 `doc_time_source` 该是 'content' 还是 'none',由
`content_time` 的返回值决定,这块已经在 deeplethe#714 + 0064 那条路径
上接好了,不动它。集成测试加了一条:「文件名日期 + 正文无日期」、
「中文文件名」、「ISO 文件名 + 中文正文」三种都走文件名解析。

前端:
- Doc 接口补上 doc_time / doc_time_source 字段
- DocViewer 头把 doc_time(文档日期)和 created_at(上传时刻)
  分两段显示,不再合并成一个「日期」格—— 跨时区归档时,
  看文档的人会把它俩错当成同一件事
- i18n(en/zh)补 docDate / docDateFromContent / uploadedAt 字符串

Signed-off-by: rollroyces <rollroyces@users.noreply.github.com>
Maintainer edits on deeplethe#979. doc_time is a calendar date stored as that day's UTC midnight, so the
viewer reads it with fmtTime like every other world date; read in local time, a reader west of
UTC saw the day before. content_time checks the extension once and takes the stem directly.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Wayland Yang <wayland0916@gmail.com>

@WaylandYang WaylandYang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, rollroyces. This is cut 1 as agreed on #610: the filename first, then the first line, full ISO or full Chinese dates only, text uploads only, and the database test covers the three shapes.

I pushed one small commit so it can land now:

  • The viewer read doc_time with toLocaleDateString. doc_time is a calendar date stored as that day's UTC midnight, so a reader west of UTC saw the day before, which is the cross-timezone case you set out to fix. It now goes through fmtTime, as the other world dates do. The upload time stays local, since it is a real moment.
  • content_time checked the extension twice and went through a helper that only called file_stem; it now checks once.

The Library list is the natural next cut, as you say. Landing this one. Thanks again.

@WaylandYang WaylandYang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer review: sound, landing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An upload can say when it was written

2 participants