Hugo 模板指南:深入解析 time.Time.Hour 方法(含时区语义与实战示例)
2026/9/20 3:14:04 网站建设 项目流程
  • 开发工具
  • 前端
  • CLI

【免费下载链接】hugo

The world’s fastest framework for building websites.

项目地址:https://gitcode.com/gh_mirrors/hu/hugo
点击查看免费下载

本文以 Hugo 官方方法参考文档 Hour.md 为主体,系统讲解 Hugo 模板中time.Time值调用.Hour方法时的返回值语义、取值范围、时区影响机制,并结合仓库源码(tpl/time/time.go)剖析time.AsTime的底层解析逻辑,给出按小时分组、时段问候等可直接复用的实战写法。读完本文,你将能准确预测任意时间值调用.Hour的结果,并规避时区导致的“差 8 小时”类经典陷阱。

方法签名与返回值

.Hour是 Go 标准库time.Time类型的内置方法,Hugo 模板引擎直接暴露给模板使用,属于time命名空间下的Time methods系列(详见 methods/time/_index.md)。

依据 Hour.md 的 front matter 定义,该方法的元数据如下:

项目
签名TIME.Hour
返回类型int
语义返回给定time.Time值在一天中的小时数
取值范围[0, 23]

方法本身不接受任何参数,也不会修改原始时间值,它只是一个只读的取值器(getter),返回的是该时间点在所在时区下的“小时”分量。

基础用法

官方文档给出了最简洁的用法示例,先用time.AsTime将字符串时间解析为time.Time值,再调用.Hour取出小时:

{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} {{ $t.Hour }} → 23

示例字符串2023-01-27T23:44:58-08:00是一个带-08:00时区偏移的 RFC 3339 时间,其本地时间为 23 点 44 分 58 秒,因此.Hour返回23

结合同目录下的兄弟方法文档,可以直观看出这一系列取值方法的协作关系——它们分别抽取时间的不同分量:

{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} {{ $t.Hour }} → 23 {{/* 小时,范围 [0, 23] */}} {{ $t.Minute }} → 44 {{/* 分钟,范围 [0, 59],见 Minute.md */}} {{ $t.Day }} → 27 {{/* 当月第几天,见 Day.md */}}

提示:.Hour.Minute.Second一样都属于“日历分量”取值器。Hugo 的 methods 文档目录 docs/content/en/methods/time/ 下完整收录了HourMinuteSecondDayMonthYearYearDayWeekday等所有同类方法,可按需查阅。

时区语义:为什么结果可能“差 8 小时”

.Hour返回的是时间值在其所在时区下的小时数,而非 UTC 小时数,这一点是理解该方法的关键。源码层面,time.AsTime的实现位于 tpl/time/time.go:

// AsTime converts the textual representation of the datetime string into // a time.Time interface. func (ns *Namespace) AsTime(v any, args ...any) (any, error) { loc := ns.location if len(args) > 0 { locStr, err := cast.ToStringE(args[0]) if err != nil { return nil, err } loc, err = time.LoadLocation(locStr) if err != nil { return nil, err } } return htime.ToTimeInDefaultLocationE(v, loc) }

从源码结构可以推断出以下行为:

  1. 默认时区:当AsTime只传一个参数时,使用ns.location,即站点配置的默认时区(对应 Hugo 配置文件中的timeZone设置),最终经由htime.ToTimeInDefaultLocationE(位于 common/htime/time.go)完成解析。
  2. 显式时区AsTime支持可选的第二个参数指定 IANA 时区名(如"Asia/Shanghai"),此时会通过time.LoadLocation加载对应时区再解析。

因此,{{ time.AsTime "2023-01-27T23:44:58-08:00" }}这个字符串自带的-08:00偏移已经明确了时间点;而不带偏移的字符串(如"2023-01-27 23:44:58")则会按站点默认时区解释,此时.Hour的结果直接取决于配置文件中的timeZone设置。这也就是实际开发中最常见的“本地时间与预期相差整小时数”问题的根源——务必确认站点timeZone与你的目标时区一致。

实战场景一:按小时对内容分组与归档

.Hour最常见的用途是按小时维度聚合内容。例如在列表模板中按小时统计某天的文章发布分布:

{{ $byHour := dict }} {{ range where site.RegularPages "Type" "posts" }} {{ $h := .Date.Hour }} {{ $byHour = merge $byHour (dict (string $h) (add (index $byHour (string $h) | default 0) 1)) }} {{ end }}

更直接的场景是单页展示“发布时间的小时”:

<p>本文发布于当天第 {{ .Date.Hour }} 时(24 小时制)</p>

其中.Date是页面 front matter 中的日期字段,Hugo 会将其解析为time.Time值(受站点timeZone影响),因此.Date.Hour的结果同样遵循上文所述的时区语义。

实战场景二:根据小时生成时段问候语

结合比较运算符,可以轻松实现按小时分段的展示逻辑:

{{ $h := now.Hour }} {{ if lt $h 6 }} 凌晨好 {{ else if lt $h 12 }} 上午好 {{ else if lt $h 18 }} 下午好 {{ else }} 晚上好 {{ end }}

这里使用了now.Hour——now由 tpl/time/time.go 中的Now方法返回,其内部调用htime.Now()(支持 Hugo 的--clock参数模拟时间),返回当前本地时间。lt(小于)比较符与数值型int返回值配合,形成清晰的分支判断。

相关方法与边界说明

.Hour的返回值为int,因此可以直接参与算术、比较与printf格式化,例如补零输出:

{{ printf "%02d" .Date.Hour }} {{/* 输出如 09、23 */}}

取值边界:合法范围是0(午夜 00:00)到23(23:00–23:59),不存在 24 或负数,因为 Go 的time.Time内部已保证时间归一化。若要获取 12 小时制的小时数,需要自行转换:

{{ $h12 := mod (sub .Date.Hour 1) 12 | add 1 }} {{/* 1–12 循环 */}}

小结

  • .Hour返回int类型的小时分量,范围[0, 23],签名TIME.Hour,无需参数;
  • 结果依赖时间值所在时区:字符串自带偏移时按偏移解释,否则按站点timeZonetime.AsTime第二参数可覆盖)解释;
  • 底层实现见 tpl/time/time.go,其中AsTimehtime.ToTimeInDefaultLocationE是解析与默认时区落地的关键调用链;
  • 官方完整参考见 docs/content/en/methods/time/Hour.md,可与 Minute.md、Day.md 等兄弟文档组合使用。
  • 开发工具
  • 前端
  • CLI

【免费下载链接】hugo

The world’s fastest framework for building websites.

项目地址:https://gitcode.com/gh_mirrors/hu/hugo
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询