这几天在给博客加几篇“歌名接龙体”的文章,比如:
- 《我们的故事》(slug: 446)
- 《晴天里的简单爱》(slug: 447)
- 《K 歌之王》(slug: 448)
本地文件都在,draft: false,路径也都是 content/posts/*.md,按理说跑 hugo serve 的时候,在列表页和归档页里都应该能看到这三篇新文章。
但实际情况是:hugo serve 正常启动,其他文章都在,这三篇就是不出现,像是完全没被 Hugo 识别到一样。这篇算是整个排查过程的一个小记录,也顺便总结下 Hugo 里“未来文章 + 时区”的坑。
1. 现象:文件都在,但 hugo serve 里看不到文章
三篇文章的 frontmatter 大致是这样的:
---
title: "我们的故事"
categories: [ "音乐" ]
tags: [ "音乐" ]
draft: false
slug: "446"
date: "2026-03-12 20:08:00"
---
另外两篇只是标题、slug、时间有点差异:
slug: "447"
date: "2026-03-12 20:10:00"
slug: "448"
date: "2026-03-12 20:20:00"
构建的时间是本地(WSL)显示的:
date
Thu Mar 12 23:28:24 CST 2026
从“人类直觉”看:23:28 已经晚于 20:xx 了,怎么也不应该被当作未来文章。但 hugo serve 的页面上,就是看不到这三篇。
2. 第一反应:Hugo 把它们当成 future 了?
Hugo 提供了一个很有用的命令,可以列出“未来文章”:
hugo list future
输出直接把问题暴露了:
path,slug,title,date,expiryDate,publishDate,draft,permalink,kind,section
content/posts/448.md,448,K歌之王,2026-03-12T20:20:00Z,0001-01-01T00:00:00Z,2026-03-12T20:20:00Z,false,https://bianle.me/posts/448/,page,posts
content/posts/447.md,447,晴天里的简单爱,2026-03-12T20:10:00Z,0001-01-01T00:00:00Z,2026-03-12T20:10:00Z,false,https://bianle.me/posts/447/,page,posts
content/posts/446.md,446,我们的故事,2026-03-12T20:08:00Z,0001-01-01T00:00:00Z,2026-03-12T20:08:00Z,false,https://bianle.me/posts/446/,page,posts
注意上面时间的尾巴:T20:20:00Z、T20:10:00Z、T20:08:00Z,这个 Z 表示的是 UTC 时间。
换句话说,虽然我在东八区(CST)看是 23:28,但 Hugo 这边拿到的时间是:
- 当前时间:2026-03-12 15:28:xx UTC
- 文章时间:2026-03-12 20:08:00 / 20:10:00 / 20:20:00 UTC
在 UTC 视角下,这三篇当然还是“未来文章”,于是很自然地就被 Hugo 当成 future 给过滤掉了,最后在 hugo serve 和正式构建时都压根不会把它们生成出来,看起来就像“文件在仓库里,但项目里不存在”一样。
3. 结论:是 Hugo 的时区设置问题
问题的根源就是:Hugo 在处理日期时默认用的是 UTC,而我在 frontmatter 里写的是“本地时间”,没有带时区信息。
比如:
date: "2026-03-12 20:08:00"
对于我来说,这是 “2026-03-12 20:08:00 CST(UTC+8)”;
但对 Hugo 来说,如果没有额外配置,它会把这当成 “2026-03-12 20:08:00 UTC” 来算。
因此,只要构建时间 < 文章的 UTC 时间,这篇文章就会出现在 hugo list future 里,并在正常构建时被过滤掉。
4. 解决方式:指定 timeZone + 视情况允许 future
4.1 在 Hugo 配置里指定时区(推荐)
在 hugo.yml 里增加(或确认已经存在):
timeZone: Asia/Shanghai
这样 Hugo 会按 Asia/Shanghai 时区来解析不带时区的 date 字段,就不会再出现“人类看起来不是未来、但 Hugo 眼里是未来”的情况。
改完之后,可以重新跑一下:
hugo list future
如果一切正常,这三篇文章就不会再出现在列表里了。
4.2 允许构建 future 文章(按需使用)
有时候你故意想把某些文章当成“未来投稿”,或者干脆不在意时间提前一点,可以在配置里允许构建 future 文章:
build:
future: true
或者在构建命令里加参数:
hugo --buildFuture
这样即便 Hugo 认为某些文章是 future,也会照常生成,不会 404。
不过这个选项更像是兜底,根本原因还是要把时区和时间写准。
4.3 在 frontmatter 里写带时区的时间(更严格)
如果想写得更明确一点,可以在 frontmatter 里直接写 ISO 8601 带时区的时间:
date: "2026-03-12T20:08:00+08:00"
这样无论 Hugo 用什么时区默认值,这个时间都表示“东八区的 20:08:00”,不会被误判。
5. 可以快速排查的命令小抄
之后再遇到“文章写了,在 hugo serve 里却看不到”的情况,可以直接按这个顺序排查:
-
看是不是 future 或 draft
hugo list future hugo list drafts -
确认访问路径
对于
content/posts/446.md且slug: "446"的文章,一般访问路径是:/posts/446/而不是
/446/。 -
检查时区和
timeZone配置-
运行
date看构建机本地时间; -
运行
hugo list future看 Hugo 眼里的时间(注意是否带Z); -
在
hugo.yml里加上:timeZone: Asia/Shanghai
-
-
必要时允许 future
build: future: true或者临时:
hugo --buildFuture
6. 小结
这次的坑,本质上是:
本地时间是东八区,frontmatter 里也按东八区在写,但 Hugo 默认按 UTC 来理解这些时间,结果文章刚写完,在 Hugo 眼里还是 future,于是构建时直接被吃掉了。
解决方案很简单:
- 明确告诉 Hugo:
timeZone: Asia/Shanghai; - 或者在需要时加上
build.future: true/--buildFuture; - 更严谨一点的话,在 frontmatter 里用带时区的 ISO 时间。
记住一个命令就行:
hugo list future
以后只要文章“明明存在却消失不见”,先问问 Hugo:
在你眼里,我是不是还活在未来?