- 开发工具
- 前端
- CLI
【免费下载链接】hugo
The world’s fastest framework for building websites.
本篇技术指南深入讲解 Hugo 静态站点生成器中的Page.ExpiryDate方法:如何通过 front matter 为页面设置过期日期、Hugo 默认跳过过期页面的构建机制、--buildExpired命令行标志与buildExpired配置项的作用,以及如何在模板中对time.Time类型的返回值进行格式化与本地化。读完本文,你将能精确控制"限时内容"的发布与下线行为,并理解 Hugo 在构建期判定过期页面的底层逻辑。
方法概览:签名与返回值
ExpiryDate是 Hugo 页面(Page)对象的一个方法,返回给定页面的过期日期。其完整定义如下:
- 返回类型:
time.Time(Go 标准库time包的时间类型) - 方法签名:
PAGE.ExpiryDate
在源码层面,该方法由pageMeta结构体实现,直接返回页面配置中解析好的过期时间:
// hugolib/page__meta.go func (m *pageMeta) ExpiryDate() time.Time { return m.pageConfig.Dates.ExpiryDate }从源码结构看,ExpiryDate、Date、PublishDate、Lastmod四个日期方法共用同一套Dates字段聚合,统一在页面元数据加载阶段从 front matter 与配置中解析,因此它们在返回值类型与时间处理行为上保持一致。
在 front matter 中设置过期日期
过期日期通过页面的 front matter 字段expiryDate设置。以下是一个 TOML 格式的 front matter 示例(对应文档content/news/article-1.md):
title = 'Article 1' expiryDate = 2024-10-19T00:32:13-07:00同样地,YAML 格式也可以设置该字段:
--- title: 'Article 1' expiryDate: 2024-10-19T00:32:13-07:00 ---关于日期值的格式,需要关注以下几点:
- 示例中的
2024-10-19T00:32:13-07:00是 RFC 3339 标准时间戳,包含时区偏移量-07:00; - 源码测试(hugolib/dates_test.go)验证了 Hugo 对短日期(如
2099-07-13)与长日期(如2099-07-13 15:28:01)两种写法的解析能力,同时覆盖了 TOML 与 YAML、带引号与不带引号等组合场景; - 日期解析会遵循站点配置的时区(
timeZone),同一篇内容在多语言站点中按各语言配置的时区解析后,ExpiryDate返回的本地时间会随之变化——这正是TestTimeZones测试所验证的行为(英文站点返回+0000 UTC,挪威语站点返回-0400 AST)。
默认行为:过期页面会被自动排除
Hugo 的默认行为是:构建项目时排除所有已过期的页面。也就是说,一旦当前时间超过了expiryDate设定的时刻,该页面便不会出现在生成的站点中,从而实现"限时内容自动下线"。
这一行为在构建调度源码中有直接体现。站点在决定是否渲染某个页面时,会调用shouldBuild判定函数(hugolib/site.go):
func shouldBuild(buildFuture bool, buildExpired bool, buildDrafts bool, Draft bool, publishDate time.Time, expiryDate time.Time, ) bool { if !(buildDrafts || !Draft) { return false } hnow := htime.Now() if !buildFuture && !publishDate.IsZero() && publishDate.After(hnow) { return false } if !buildExpired && !expiryDate.IsZero() && expiryDate.Before(hnow) { return false } return true }其中的关键判定逻辑为:
- 若页面设置了
expiryDate(即返回值非零值),且该时间早于当前时刻,同时未开启buildExpired,则页面不参与构建; - 与之对称的是
publishDate(发布日期)逻辑:若发布日期晚于当前时刻且未开启buildFuture,页面同样会被跳过。两者共同构成了 Hugo 对"未发布"与"已过期"内容的双重建构门控。
构建已过期页面:--buildExpired标志
如果出于归档、预览或内容审计等目的需要强制构建并输出已过期页面,可以使用命令行标志:
hugo --buildExpired在 Hugo 开发服务器中同样支持:
hugo server --buildExpired该标志对应的配置字段为buildExpired,在源码配置结构中定义如下(config/allconfig/allconfig.go):
// Whether to build content with expiryDate in the past. BuildExpired bool因此,除了命令行标志,你也可以在站点配置文件(如hugo.toml)中将其固化为默认行为:
buildExpired = true配置项说明:
| 配置 / 标志 | 默认值 | 作用 |
|---|---|---|
buildExpired/--buildExpired | false | 为true时构建所有expiryDate已过的页面 |
buildFuture/--buildFuture | false | 为true时构建所有publishDate在未来(未到发布时间)的页面 |
buildDrafts/--buildDrafts | false | 为true时构建标记为draft的草稿页面 |
需要注意的是,开启buildExpired只是让过期页面进入构建流程,页面的ExpiryDate值本身不会改变,模板中依然可以读取到真实的过期时间用于展示。
模板中的格式化与本地化
由于ExpiryDate的返回值是 Go 的time.Time类型,你可以直接在模板中结合 Hugo 的日期函数与模板方法对其进行格式化与本地化:
- 使用
time.Format函数按 Hugo 的日期格式说明符输出; - 或直接使用
time包提供的时间方法(如.Month、.Year、.UTC等)。
例如,在 Go 模板中输出"中格式"日期:
{{ .ExpiryDate | time.Format ":date_medium" }} → Oct 19, 2024其中:date_medium是 Hugo 内置的日期格式速记符,会按当前站点语言环境渲染为本地化格式。由于多语言站点的日期渲染与语言配置(含时区)相关,建议在模板中统一使用time.Format而非硬编码的字符串格式,以保证各语言版本输出的日期形态一致。
在模板测试中也可以看到,页面对象暴露的ExpiryDate可直接与safeHTML等模板函数组合使用(hugolib/dates_test.go):
ExpiryDate: {{ .ExpiryDate | safeHTML }}日期回退机制:未设置时的 fallback 行为
示例中我们在 front matter 里显式设置了expiryDate。在 Hugo 的默认配置下,ExpiryDate方法返回的就是 front matter 中的该字段值。不过这一行为是可配置的:Hugo 允许通过frontmatter配置为四个日期字段(date、lastmod、publishDate、expiryDate)设置回退取值顺序,当某个字段未在 front matter 中定义时,按配置的优先级依次回退。
以expiryDate为例,默认回退序列为expiryDate→unpublishdate,即:若 front matter 未定义expiryDate,则回退读取unpublishdate字段;若仍未定义,则得到零值时间。这一机制在 docs/content/en/configuration/front-matter.md 中有详细说明。
若希望使用 Hugo 的默认日期回退序列,可在 front matter 配置中显式使用:default标记。对日期回退规则更细粒度的控制(例如自定义多字段回退顺序),请参阅 front-matter 配置文档 中的 "Dates" 一节。
零值时间的处理
当页面既未设置expiryDate、也未命中任何回退字段时,ExpiryDate返回 Go 时间的零值(0001-01-01 00:00:00 +0000 UTC)。这一点可以从集成测试的输出中得到印证(hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go):
Dates: Date: 2023-03-01|Lastmod: 2023-03-01|PublishDate: 2023-03-01|ExpiryDate: 0001-01-01|同时,shouldBuild的判定逻辑对零值时间做了显式保护(!expiryDate.IsZero()),因此未设置过期日期的页面永远不会被"过期"判定误伤。
实战建议
- 限时活动页:在 front matter 中设置
expiryDate,站点构建后活动结束即自动下线,无需手动删除内容; - 归档场景:如需保留已过期页面供历史访问,可在
hugo.toml中开启buildExpired = true,并在模板中通过if .ExpiryDate.After(now)之类的条件区分"当前有效"与"已过期"内容; - 多语言与多时区:明确各语言站点的
timeZone配置,避免因时区差异导致页面提前或延迟过期; - 格式一致性:统一使用
time.Format输出过期日期,确保站点内日期展示风格一致且本地化正确。
参考资源
- 方法实现源码:
ExpiryDate()的pageMeta实现 - 构建判定逻辑:
shouldBuild函数与过期/未来页面排除规则 - 配置结构定义:
BuildExpired配置字段 - 日期与时区测试:
TestTimeZones等测试覆盖的日期解析与时区行为 - front-matter 日期配置:日期字段回退机制详解
- 开发工具
- 前端
- CLI
【免费下载链接】hugo
The world’s fastest framework for building websites.
相关推荐
Hugo 页面日期(Page.Date):front matter 日期解析、`time.Format` 本地化与源码实现解析
Hugo 页面日期(Page.Date):front matter 日期解析、 time.Format 本地化与源码实现解析 导读 本文围绕 Hugo 页面方法
开发工具前端CLIHugo 页面方法 GroupByExpiryDate:按过期日期分组内容
Hugo 页面方法 GroupByExpiryDate:按过期日期分组内容 本指南详解 Hugo 中 Pages.GroupByExpiryDate 方法的用法
开发工具前端CLIHugo 页面方法 PublishDate:发布日期的取值、格式化与 future 页面构建控制
Hugo 页面方法 PublishDate:发布日期的取值、格式化与 future 页面构建控制 PublishDate 是 Hugo 中 Page 对象返回页
开发工具前端CLI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考