fix(drivers/189): support updated 189 time format - #2919
Conversation
|
关联 issue #2917,同根因:189 API 返回新时间格式(年份后带逗号、自带时区,以及 AM/PM 前使用 U+202F 窄不换行空格),现有 |
f3b2866 to
9479362
Compare
a68e16c to
d4beaa8
Compare
PIKACHUIM
left a comment
There was a problem hiding this comment.
🙏 感谢贡献
感谢 @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.go 和 drivers/189_tv/help.go
改动意图:
修复 Time.Unmarshal 方法,使其能够解析天翼云盘 API 返回的新时间格式,同时保持对旧格式的兼容性。
代码修改逻辑:
-
Unicode 空格处理(第 75-77 行):
- 新增对 U+202F(窄不换行空格)和 U+00A0(不换行空格)的处理
- 将这两种 Unicode 空格统一替换为普通空格(ASCII 0x20)
- 原因:新 API 返回的时间串中,AM/PM 前使用的是 Unicode 空格而非普通空格,导致 Go 的
time.Parse无法识别
-
时区处理优化(第 81 行):
- 原逻辑:直接在时间串后追加
+08时区 - 新逻辑:分两种情况尝试解析
- 先尝试原始串(可能自带时区,如
"Aug 11, 2026, 10:37:18 PM +08") - 再尝试追加
+08的串(向后兼容旧格式,如"Aug 11, 2026 10:37:18 PM")
- 先尝试原始串(可能自带时区,如
- 避免了重复添加时区导致解析失败
- 原逻辑:直接在时间串后追加
-
新增时间格式模板(第 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使用
- 添加
-
双层循环解析(第 81-89 行):
- 外层循环:遍历两种时间串(原始 / 追加时区)
- 内层循环:遍历三种时间格式模板
- 任意一种组合解析成功即跳出
- 保证了最大的兼容性
合理性评估:
✅ 优点:
- 问题定位准确:精准识别了问题的根本原因(Unicode 空格 + 时间格式变更)
- 向后兼容:保留了对旧格式的支持,不会影响现有数据
- 代码简洁:使用嵌套循环优雅地处理多种格式组合,没有引入复杂的条件分支
- 两个驱动同步修改:189pc 和 189_tv 采用完全一致的修复方案,保证了一致性
- 注释清晰:中文注释详细说明了问题背景和解决方案
- 时区硬编码:代码中硬编码了
+08时区,是否所有天翼云盘用户都使用东八区?(不过考虑到天翼云盘是中国电信的服务,硬编码东八区应该是合理的)
详细建议:
- 性能优化(优先级:低)
当前实现使用双层循环,最坏情况下需要尝试 6 次解析(2 种时间串 × 3 种格式)。虽然时间解析本身很快,但理论上可以通过格式预判进一步优化。
不过,考虑到:
- 这是低频操作(仅在解析 API 响应时调用)
- 当前双层循环实现更简洁、可维护性更强
- 过早优化可能引入不必要的复杂度
建议:保持当前实现即可,除非未来性能分析显示此处是瓶颈。
drivers/189pc/help_test.go 和 drivers/189_tv/help_test.go
改动意图:
新增单元测试,覆盖所有时间格式变体,确保修复方案的正确性。
代码修改逻辑:
-
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 空格变体 1no-break space (U+00A0):Unicode 空格变体 2
-
TestTimeUnmarshalRejectsInvalid:负面测试,确保非法时间串(如 25 点)会被拒绝
合理性评估:
✅ 优点:
- 测试覆盖全面:覆盖了所有已知的时间格式变体和 Unicode 空格问题
- 包含负面测试:验证了错误处理逻辑
- 测试可读性强:使用表驱动测试,每个用例都有清晰的名称
- 测试数据真实:使用了 issue 中报告的实际时间串
❌ 问题:无
🎯 总体评价
功能性:⭐⭐⭐⭐⭐ - 完美解决了 issue 中描述的问题,同时保持向后兼容
安全性:⭐⭐⭐⭐⭐ - 无安全隐患,仅涉及时间解析逻辑
代码质量:⭐⭐⭐⭐⭐ - 代码简洁清晰,注释完善,测试覆盖充分
实现方案:⭐⭐⭐⭐⭐ - 采用了最直接有效的解决方案,兼容性好
建议操作:
- ✅ Approve(建议合并)
理由:
这是一个高质量的 Bug 修复 PR,具备以下优势:
- 问题定位精准:准确识别了天翼云盘 API 时间格式变更的根本原因(逗号、12小时制、Unicode 空格、时区)
- 修复方案完善:
- 处理了 Unicode 空格问题(U+202F、U+00A0)
- 添加了新的时间格式模板
- 优雅地处理了时区的有无
- 保持了对旧格式的向后兼容
- 测试覆盖全面:6 个正面测试用例 + 1 个负面测试用例,覆盖了所有已知格式变体
- 实际验证充分:PR 描述中提到已在本地 Docker 环境使用真实 189 存储验证,S3 PUT 返回 200,日志无 parsing time 错误
- 代码质量高:
- 两个驱动(189pc、189_tv)同步修改,保证一致性
- 注释清晰,解释了问题背景
- 代码简洁,使用嵌套循环而非冗长的 if-else
- 符合贡献规范:
- 勾选了所有必要的检查清单
- 声明了 AI 辅助内容并添加了 Co-Authored-By
- 关联了正确的 issue
唯一的小遗憾:PR 描述中提到 go test ./... 因预先存在的 vet 错误未通过,但这与本次改动无关,不影响合并。
建议立即合并,这个 Bug 影响了所有使用天翼云盘 + crypt 加密的用户,应尽快发布修复版本。
PIKACHUIM
left a comment
There was a problem hiding this comment.
感谢您的贡献,有 几个小疑问需要确认:
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
d4beaa8 to
ae3d1a6
Compare
答复三个问题@PIKACHUIM 感谢 review!针对三个问题的答复: 1. 189 网页端是否存在这个问题 2. 硬编码东八区是否有问题 3. 防御性修改
若未来 189 再次变更格式,模板是布局列表,新增一行即可扩展;不额外预加 RFC3339 等未出现的格式,避免过度设计。 Co-Authored-By: deepseek-v4-flash |
Summary / 摘要
189 API 变更了时间返回格式,现有
Time.Unmarshal无法解析,导致 189pc/189_tv 驱动所有写操作失败(Put → 500)。新增模板
Jan 2, 2006, 3:04:05 PM -07(带逗号,312 小时制配 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:
Related Issues / 关联 Issue
Fixes #2917
Testing / 测试
go test ./...执行命令:
go test ./...因 pre-existing vet 错误(drivers/189pc/utils.go:358非常量格式串)未通过,与本次改动无关。Checklist / 检查清单
/ 我已阅读 CONTRIBUTING。
/ 我确认此贡献符合仓库许可证、贡献规范和行为准则。
gofmt,go fmt, orprettierwhere applicable./ 我已按适用情况使用
gofmt、go fmt或prettier格式化变更代码。/ 我已在适用情况下请求相关维护者或代码所有者审查。
AI Disclosure / AI 使用声明
/ 此 PR 包含 AI 辅助内容。
Tools used / 使用工具:
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-Byattribution./ 我已确保所有 AI 辅助提交都包含
Co-Authored-By归属信息。I can reproduce all AI-assisted content included in this PR without any AI tools.
/ 我可以在没有任何 AI 工具的情况下重现此 PR 中包含的所有 AI 辅助内容。