Skip to content

fix(drivers/189): support updated 189 time format - #2919

Merged
PIKACHUIM merged 1 commit into
OpenListTeam:mainfrom
shelken:fix/189-time-parse
Aug 14, 2026
Merged

fix(drivers/189): support updated 189 time format#2919
PIKACHUIM merged 1 commit into
OpenListTeam:mainfrom
shelken:fix/189-time-parse

Conversation

@shelken

@shelken shelken commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary / 摘要

189 API 变更了时间返回格式,现有 Time.Unmarshal 无法解析,导致 189pc/189_tv 驱动所有写操作失败(Put → 500)。

  • 新增模板 Jan 2, 2006, 3:04:05 PM -07(带逗号,3 12 小时制配 PM),覆盖 Aug 11, 2026, 10:37:18 PM +08

  • 解析前将 U+202F 窄不换行空格、U+00A0 不换行空格统一替换为普通空格

  • 对可能不带时区的串,先试原串再试追加 +08(向后兼容)

  • 同步修复 189pc 与 189_tv 两个驱动

  • This PR has breaking changes.
    / 此 PR 包含破坏性变更。

  • This PR changes public API, config, storage format, or migration behavior.
    / 此 PR 修改了公开 API、配置、存储格式或迁移行为。

  • This PR requires corresponding changes in related repositories.
    / 此 PR 需要关联仓库同步修改。

Related repository PRs / 关联仓库 PR:

  • OpenList-Frontend: N/A
  • OpenList-Docs: N/A

Related Issues / 关联 Issue

Fixes #2917

Testing / 测试

  • go test ./...
  • Manual test / 手动测试: 本地 docker 运行 patched 镜像 + 真实 189 存储,S3 PUT 200,日志 0 个 parsing time 错误

执行命令:

go test -vet=off -run TestTimeUnmarshal ./drivers/189pc/ ./drivers/189_tv/
--- PASS: TestTimeUnmarshal (0.00s)
    --- PASS: TestTimeUnmarshal/numeric_date
    --- PASS: TestTimeUnmarshal/legacy_month_date
    --- PASS: TestTimeUnmarshal/new_format_with_tz
    --- PASS: TestTimeUnmarshal/new_format_no_tz
    --- PASS: TestTimeUnmarshal/narrow_no-break_space_(U+202F)
    --- PASS: TestTimeUnmarshal/no-break_space_(U+00A0)
--- PASS: TestTimeUnmarshalRejectsInvalid (0.00s)

go test ./... 因 pre-existing vet 错误(drivers/189pc/utils.go:358 非常量格式串)未通过,与本次改动无关。

Checklist / 检查清单

  • I have read CONTRIBUTING.
    / 我已阅读 CONTRIBUTING
  • I confirm this contribution follows the repository license, contribution policy, and code of conduct.
    / 我确认此贡献符合仓库许可证、贡献规范和行为准则。
  • I have formatted the changed code with gofmt, go fmt, or prettier where applicable.
    / 我已按适用情况使用 gofmtgo fmtprettier 格式化变更代码。
  • I have requested review from relevant maintainers or code owners where applicable.
    / 我已在适用情况下请求相关维护者或代码所有者审查。

AI Disclosure / AI 使用声明

  • This PR includes AI-assisted content.
    / 此 PR 包含 AI 辅助内容。

Tools used / 使用工具:

  • ChatGPT
  • Codex
  • GitHub Copilot
  • Claude
  • Gemini
  • Other (please specify) / 其他(请注明):

Usage scope / 使用范围:

  • Code generation / 代码生成

  • Refactoring / 重构

  • Documentation / 文档

  • Tests / 测试

  • Translation / 翻译

  • Review assistance / 审查辅助

  • I have reviewed and validated all AI-assisted content included in this PR.
    / 我已审核并验证此 PR 中的所有 AI 辅助内容。

  • I have ensured that all AI-assisted commits include Co-Authored-By attribution.
    / 我已确保所有 AI 辅助提交都包含 Co-Authored-By 归属信息。

  • I can reproduce all AI-assisted content included in this PR without any AI tools.
    / 我可以在没有任何 AI 工具的情况下重现此 PR 中包含的所有 AI 辅助内容。

@shelken

shelken commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

关联 issue #2917,同根因:189 API 返回新时间格式(年份后带逗号、自带时区,以及 AM/PM 前使用 U+202F 窄不换行空格),现有 Time.Unmarshal 模板无法解析。

@shelken
shelken force-pushed the fix/189-time-parse branch from f3b2866 to 9479362 Compare August 11, 2026 20:40
@shelken shelken changed the title fix(drivers/189): support new 189 time format with comma, timezone and U+202F fix(drivers/189): support updated 189 time format Aug 11, 2026
@shelken
shelken force-pushed the fix/189-time-parse branch 2 times, most recently from a68e16c to d4beaa8 Compare August 11, 2026 20:48

@PIKACHUIM PIKACHUIM left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🙏 感谢贡献

感谢 @shelken 提交此PR!我已完成代码评审,以下是评审结果。


🤖 AI 自动审核声明

本评审报告由 AI 自动生成,当前使用 Claude Opus 5 模型进行分析。

⚠️ AI 分析结果仅供参考,可能存在误判或遗漏。如您发现任何问题或有不同意见,欢迎随时提出讨论和纠正。

⚠️ 重要提醒:即使 AI 评审认为代码质量良好且建议合并,最终是否合并仍需由项目维护者进行人工判定。项目维护者会综合考虑代码质量、项目规划、技术方向、团队资源等多方面因素做出决策。


📖 PR背景与需求

PR标题:fix(drivers/189): support updated 189 time format

关联Issue:Fixes #2917 - [BUG] crypt驱动挂载天翼云盘客户端时上传文件报错parsing time

需求说明

天翼云盘(189云盘)API 在近期变更了时间字段的返回格式,导致现有的 Time.Unmarshal 方法无法正确解析,从而导致 189pc(天翼云盘客户端)和 189_tv(天翼云盘TV版)两个驱动的所有写操作失败(返回 500 错误)。

具体问题表现:

  • 用户上传文件到天翼云盘(裸盘)→ 正常
  • 用户上传文件到天翼云盘 + crypt 加密 → 报错 parsing time "Aug 11, 2026, 7:20:03\xe2\x80\xafPM +08",但文件实际上传成功
  • 错误原因:API 返回的时间格式从原来的 "Aug 11, 2026 10:37:18 PM" 变更为 "Aug 11, 2026, 10:37:18 PM +08"(年份后多了逗号,且自带时区)

预期目标

修复时间解析逻辑,支持新的时间格式,同时保持对旧格式的向后兼容,确保所有写操作能够正常完成。


📋 问题摘要

  • ⚠️ 安全性:无安全问题
  • ⚠️ 代码质量:代码质量良好,测试覆盖充分
  • 💡 改进建议:1 处优化建议(性能优化,优先级低)

📂 逐文件分析

drivers/189pc/help.godrivers/189_tv/help.go

改动意图

修复 Time.Unmarshal 方法,使其能够解析天翼云盘 API 返回的新时间格式,同时保持对旧格式的兼容性。

代码修改逻辑

  1. Unicode 空格处理(第 75-77 行):

    • 新增对 U+202F(窄不换行空格)和 U+00A0(不换行空格)的处理
    • 将这两种 Unicode 空格统一替换为普通空格(ASCII 0x20)
    • 原因:新 API 返回的时间串中,AM/PM 前使用的是 Unicode 空格而非普通空格,导致 Go 的 time.Parse 无法识别
  2. 时区处理优化(第 81 行):

    • 原逻辑:直接在时间串后追加 +08 时区
    • 新逻辑:分两种情况尝试解析
      • 先尝试原始串(可能自带时区,如 "Aug 11, 2026, 10:37:18 PM +08"
      • 再尝试追加 +08 的串(向后兼容旧格式,如 "Aug 11, 2026 10:37:18 PM"
    • 避免了重复添加时区导致解析失败
  3. 新增时间格式模板(第 82 行):

    • 添加 "Jan 2, 2006, 3:04:05 PM -07":带逗号的月份格式 + 12小时制 + 时区
    • 添加 "Jan 2, 2006 3:04:05 PM -07":不带逗号的月份格式 + 12小时制 + 时区(向后兼容)
    • 保留 "2006-01-02 15:04:05 -07":数字格式(向后兼容)
    • 关键变化:将小时格式从 15(24小时制)改为 3(12小时制),配合 PM 使用
  4. 双层循环解析(第 81-89 行):

    • 外层循环:遍历两种时间串(原始 / 追加时区)
    • 内层循环:遍历三种时间格式模板
    • 任意一种组合解析成功即跳出
    • 保证了最大的兼容性

合理性评估

优点

  1. 问题定位准确:精准识别了问题的根本原因(Unicode 空格 + 时间格式变更)
  2. 向后兼容:保留了对旧格式的支持,不会影响现有数据
  3. 代码简洁:使用嵌套循环优雅地处理多种格式组合,没有引入复杂的条件分支
  4. 两个驱动同步修改:189pc 和 189_tv 采用完全一致的修复方案,保证了一致性
  5. 注释清晰:中文注释详细说明了问题背景和解决方案

⚠️ 疑问

  1. 时区硬编码:代码中硬编码了 +08 时区,是否所有天翼云盘用户都使用东八区?(不过考虑到天翼云盘是中国电信的服务,硬编码东八区应该是合理的)

详细建议

  1. 性能优化(优先级:低)

当前实现使用双层循环,最坏情况下需要尝试 6 次解析(2 种时间串 × 3 种格式)。虽然时间解析本身很快,但理论上可以通过格式预判进一步优化。

不过,考虑到:

  • 这是低频操作(仅在解析 API 响应时调用)
  • 当前双层循环实现更简洁、可维护性更强
  • 过早优化可能引入不必要的复杂度

建议:保持当前实现即可,除非未来性能分析显示此处是瓶颈。


drivers/189pc/help_test.godrivers/189_tv/help_test.go

改动意图

新增单元测试,覆盖所有时间格式变体,确保修复方案的正确性。

代码修改逻辑

  1. TestTimeUnmarshal:表驱动测试,覆盖 6 种时间格式

    • numeric date:旧的数字格式 "2026-08-11 10:37:18"
    • legacy month date:旧的月份格式(不带逗号)"Aug 11, 2026 10:37:18 PM"
    • new format with tz:新格式(带逗号 + 时区)"Aug 11, 2026, 10:37:18 PM +08"
    • new format no tz:新格式(带逗号,不带时区)"Aug 11, 2026, 10:37:18 PM"
    • narrow no-break space (U+202F):Unicode 空格变体 1
    • no-break space (U+00A0):Unicode 空格变体 2
  2. TestTimeUnmarshalRejectsInvalid:负面测试,确保非法时间串(如 25 点)会被拒绝

合理性评估

优点

  1. 测试覆盖全面:覆盖了所有已知的时间格式变体和 Unicode 空格问题
  2. 包含负面测试:验证了错误处理逻辑
  3. 测试可读性强:使用表驱动测试,每个用例都有清晰的名称
  4. 测试数据真实:使用了 issue 中报告的实际时间串

问题:无


🎯 总体评价

功能性:⭐⭐⭐⭐⭐ - 完美解决了 issue 中描述的问题,同时保持向后兼容

安全性:⭐⭐⭐⭐⭐ - 无安全隐患,仅涉及时间解析逻辑

代码质量:⭐⭐⭐⭐⭐ - 代码简洁清晰,注释完善,测试覆盖充分

实现方案:⭐⭐⭐⭐⭐ - 采用了最直接有效的解决方案,兼容性好

建议操作

  • ✅ Approve(建议合并)

理由

这是一个高质量的 Bug 修复 PR,具备以下优势:

  1. 问题定位精准:准确识别了天翼云盘 API 时间格式变更的根本原因(逗号、12小时制、Unicode 空格、时区)
  2. 修复方案完善
    • 处理了 Unicode 空格问题(U+202F、U+00A0)
    • 添加了新的时间格式模板
    • 优雅地处理了时区的有无
    • 保持了对旧格式的向后兼容
  3. 测试覆盖全面:6 个正面测试用例 + 1 个负面测试用例,覆盖了所有已知格式变体
  4. 实际验证充分:PR 描述中提到已在本地 Docker 环境使用真实 189 存储验证,S3 PUT 返回 200,日志无 parsing time 错误
  5. 代码质量高
    • 两个驱动(189pc、189_tv)同步修改,保证一致性
    • 注释清晰,解释了问题背景
    • 代码简洁,使用嵌套循环而非冗长的 if-else
  6. 符合贡献规范
    • 勾选了所有必要的检查清单
    • 声明了 AI 辅助内容并添加了 Co-Authored-By
    • 关联了正确的 issue

唯一的小遗憾:PR 描述中提到 go test ./... 因预先存在的 vet 错误未通过,但这与本次改动无关,不影响合并。

建议立即合并,这个 Bug 影响了所有使用天翼云盘 + crypt 加密的用户,应尽快发布修复版本。

PIKACHUIM
PIKACHUIM previously approved these changes Aug 14, 2026

@PIKACHUIM PIKACHUIM left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

感谢您的贡献,有 几个小疑问需要确认:
1、189网页端是否存在这个问题
2、硬编码东八区是否有问题
3、能否防御性修改,以防天翼云改回去,或者未来再次修改

…e and unicode spaces

189 API 变更了时间返回格式,现有 Time.Unmarshal 无法解析,导致 189pc/189_tv
驱动所有写操作失败(Put → 500)。

新格式有三种形态,现有两个模板均无法覆盖:
1. "Aug 11, 2026, 10:37:18 PM +08" — 年份后多逗号,且自带时区
2. "Aug 12, 2026, 12:35:41\u202fAM +08" — AM/PM 前为 U+202F 窄不换行空格
3. "Aug 12, 2026, 12:35:41\u00a0AM +08" — AM/PM 前为 U+00A0 不换行空格

修复(189pc/help.go、189_tv/help.go 的 Time.Unmarshal):
- 解析前将 U+202F 和 U+00A0 统一替换为普通空格
- 新增模板 "Jan 2, 2006, 3:04:05 PM -07"(带逗号,3 为 12 小时制配 PM)
- 对可能不带时区的串,先试原串再试追加 " +08"(向后兼容)

新增 help_test.go 覆盖:数字日期、旧月份格式、新格式带/不带时区、
U+202F/U+00A0 空格、非法输入。

Fixes OpenListTeam#2917

Co-Authored-By: Advanced <noreply@pi.dev>
Co-Authored-By: DeepSeek V4 Flash (2x usage) <noreply@pi.dev>
Generated-By: pi 0.84.1
@shelken

shelken commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

答复三个问题

@PIKACHUIM 感谢 review!针对三个问题的答复:

1. 189 网页端是否存在这个问题
不存在。网页端驱动 drivers/189 解析时间走 pkg/utils.MustParseCNTime,只处理数字格式 2006-01-02 15:04:05(网页 API 返回该格式),不走 189pc/189_tv 的月名格式解析;且该驱动解析失败是静默的(错误被忽略、返回零时间),不会像 189pc 那样因解析失败导致整个响应 500。OpenList 前端本身也不解析 189 原始时间串(后端解析完才返回给前端)。

2. 硬编码东八区是否有问题
没有问题。189 是中国电信服务,API 时间固定为北京时间(UTC+8),与用户所在位置无关。这也是项目既有模式:旧代码、189pc.MustParseTimepkg/utils.MustParseCNTime 三处均硬编码 +08pkg/utils 里还有现成的 CNLoc = time.FixedZone("UTC", 8*3600) 常量。且本次实现中,串自带时区时优先使用串内时区,+08 仅作为无时区串的兜底。

3. 防御性修改
已做两处:

  • 时区解析兜底从 time.Local 改为 utils.CNLoc(上一 commit 已补上)。原实现三个模板均带 -07 时区要求,无时区串必然走追加 +08 分支,time.Local 实际从未生效(属隐性正确);改为 CNLoc 后兜底语义显式化——无时区串按东八区解析,与项目其它 189 解析逻辑一致,也防止未来新增不带时区的模板时静默用错机器时区。行为零变化,测试全绿。
  • Unicode 空格归一化(U+202F/U+00A0 → 普通空格)已覆盖 189 可能替换空格的变体。

若未来 189 再次变更格式,模板是布局列表,新增一行即可扩展;不额外预加 RFC3339 等未出现的格式,避免过度设计。

Co-Authored-By: deepseek-v4-flash

@PIKACHUIM
PIKACHUIM merged commit e80ee00 into OpenListTeam:main Aug 14, 2026
8 checks passed
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.

[BUG] crypt驱动挂载天翼云盘客户端时上传文件报错parsing time

2 participants