Skip to content

fix!: use millisecond-precision timestamps for output filenames#16

Open
RachelXiaolan wants to merge 1 commit into
better-world-ai:mainfrom
RachelXiaolan:fix/ms-precision-timestamps
Open

fix!: use millisecond-precision timestamps for output filenames#16
RachelXiaolan wants to merge 1 commit into
better-world-ai:mainfrom
RachelXiaolan:fix/ms-precision-timestamps

Conversation

@RachelXiaolan

Copy link
Copy Markdown
Contributor

Summary

⚠️ Breaking change — output filenames for nanobanana-cli and chatgpt-image-cli change format.

Both CLIs use time.Now().Format("20060102-150405") (second precision) for output filenames. Two rapid invocations within the same second (e.g. from a script loop) silently overwrite the first file.

Before:

20260519-143022-full.png
chatgpt-20260519-143022.png

After:

20260519-143022-047-full.png
chatgpt-20260519-143022-047.png

The -000 suffix adds millisecond precision (3 digits, zero-padded), reducing collision risk by ~1000x. A hyphen separator is used instead of a dot to avoid confusion with file extensions.

Split out from #10 per maintainer request — see comment.

Testing

cd nanobanana-cli && go build -o /dev/null .     # OK
cd chatgpt-image-cli && go build -o /dev/null .  # OK

nanobanana-cli and chatgpt-image-cli use time.Now().Format("20060102-150405")
(second precision) for output filenames. Two rapid invocations within the
same second (e.g. from a script) silently overwrite the first file.

Changed to "20060102-150405-000" (millisecond precision) to reduce
collision risk. Uses hyphen separator to avoid confusion with file
extensions.

⚠️ BREAKING CHANGE: output filenames change from e.g.
  20260519-143022-full.png → 20260519-143022-123-full.png
Any scripts parsing these filenames will need updating.
@xpzouying

Copy link
Copy Markdown
Collaborator

PR Review — 🔴 实现 bug:-000 是字面量,不会渲染毫秒

这个 PR 想做什么(我的理解)

把 nanobanana-cli 和 chatgpt-image-cli 的输出文件名从秒精度时间戳改成毫秒精度,避免脚本循环里同一秒内多次调用相互覆盖。问题定位是真的(这两个 CLI 的 gen.go 里 timestamp 就是唯一的去重机制,没有 counter / 随机后缀),动机非常合理。

发现的问题

🔴 Blocker:Go 的 time.Format 不会把 -000 解读为毫秒

Go 的时间格式化里,小数秒占位符必须以 ., 开头(如 .000 / ,000)。单独的 000 序列不在 reference time 2006-01-02 15:04:05.000000000 任何被识别的位置上,会被当作字面量 "000" 原样输出。

实测验证(Go 1.25.1):

t1 := time.Date(2026, 5, 19, 14, 30, 22,  47000000, time.UTC) //  47ms
t2 := time.Date(2026, 5, 19, 14, 30, 22, 892000000, time.UTC) // 892ms

t1.Format("20060102-150405-000")  → "20260519-143022-000"字面量 -000
t2.Format("20060102-150405-000")  → "20260519-143022-000"字面量 -000

t1.Format("20060102-150405.000")  → "20260519-143022.047"真的毫秒
t2.Format("20060102-150405.000")  → "20260519-143022.892"真的毫秒

也就是说,PR 改完之后两次同一秒内的调用仍然得到完全相同的 stem,文件依然会覆盖。碰撞问题没解决,只是给所有文件名加了个无意义的 -000 后缀。

修复建议(任选其一)

方案 A — 接受 . 分隔符(最简单):

stem := time.Now().Format("20060102-150405.000")
// → 20260519-143022.047-full.png

方案 B — 保留 - 分隔符(符合 PR 描述意图),用 fmt.Sprintf 组合:

now := time.Now()
stem := fmt.Sprintf("%s-%03d", now.Format("20060102-150405"), now.Nanosecond()/1_000_000)
// → 20260519-143022-047-full.png

注意要捕获 now 一次再分别取秒和纳秒,否则两次 time.Now() 可能跨毫秒边界。

方案 C — . 格式化后字符串替换

stem := strings.Replace(time.Now().Format("20060102-150405.000"), ".", "-", 1)
// → 20260519-143022-047-full.png

我倾向 方案 B

  • 与 PR 描述里 "use a hyphen separator instead of a dot to avoid confusion with file extensions" 的设计意图一致
  • 比方案 C 不依赖字符串替换,意图更直接
  • 比方案 A 在 shell 里更友好(*-full.png glob 比 *.000-full.png 干净)

是否仍然属于 fix! (breaking change)?

是的,marker 本身是对的:文件名长度从 20060102-150405-full.png(24 字符)变成 20060102-150405-NNN-full.png(28 字符),任何用 sed / awk / 固定列宽切片解析文件名的下游脚本都会受影响。

不过现在的实现里,breaking change 没换来任何实际收益 —— 多出来的 -000 是字面量,碰撞还是一样存在。

Code review 其他方面

End-to-end 验证

没有实际跑 nanobanana-clichatgpt-image-cli 生成图片 —— 两个 CLI 会消耗用户的 OpenAI / 浏览器额度,而 bug 完全在纯 Go time 格式化层面,上面的 Go 单元测试已经构成充分证据。修复后建议用一段循环跑两次确认(无需 API 调用):

# 修复后本地小验证(不调用图生 API,纯打印格式)
go run -exec=echo -- '...'  # 或简单的 fmt.Println(time.Now().Format(...))

结论

⚠️ Request changes —— 改一行就能修好(任选方案 B / A / C 之一),改完后是个干净的小 PR

非常细节的发现 —— Go 的 time 格式语义化解析是个经典踩坑点。问题的定位准确、动机合理、PR 描述写得很好,只差最后这一步实现。

After merge

合入后建议给 @RachelXiaolan.all-contributorsrc 加上贡献类型(如果还没加的话):code(这两个 PR)+ review(PR#9 的高质量 review)。可以和 PR#17 的 update 一起做。

xpzouying added a commit that referenced this pull request May 21, 2026
Recognizing @RachelXiaolan for code contributions (PR #17 — Status() health
check + SilenceUsage for baidu-cli/google-cli) and pull-request reviews
(detailed technical review on PR #9, plus follow-up PR #16).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants