Hugo 模板函数 time.Duration 完整指南:以时间单位与数值构造时长并调用 Duration 方法
【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo
time.Duration是 Hugo 模板系统time命名空间下的核心函数,它接收一个时间单位(如hour、second)和一个数值,返回 Go 标准的time.Duration值,随后即可调用Seconds、Minutes、Hours等Duration方法进行换算与格式化。本文基于 Hugo 当前源码(实现位于 tpl/time/time.go)与该函数的官方文档(docs/content/en/functions/time/Duration.md),完整讲解其签名、单位取值、源码实现原理、与time.ParseDuration的差异,以及在实际模板中的典型用法。
函数签名与返回值
根据文档中声明的签名:
time.Duration TIME_UNIT NUMBER- TIME_UNIT:字符串,表示时间单位,支持全称与缩写(见下文单位表);
- NUMBER:数值,表示该单位的数量,可以是整数或可转换为整数的字符串;
- 返回值:
time.Duration,即 Go 标准库time包中的时长类型。
同时该函数注册了别名duration,因此time.Duration与duration两种写法等价。别名注册位于 tpl/time/init.go,其中还给出了管道用法示例:
{{ mul 60 60 | duration "second" }} → 1h0m0s即先计算60 * 60 = 3600,再以second为单位构造时长,得到1h0m0s。
支持的合法时间单位
time.Duration的第二个参数(时间单位)必须是下表所列取值之一,包含全称与缩写:
| Duration | Valid time units |
|---|---|
| hours | hour、h |
| minutes | minute、m |
| seconds | second、s |
| milliseconds | millisecond、ms |
| microseconds | microsecond、us、µs |
| nanoseconds | nanosecond、ns |
其中微秒同时支持 ASCII 缩写us与希腊字母µs两种写法,毫秒、纳秒等则各有一个全称与一个缩写。超出该表的单位(例如复数形式hours、minutes)会被判定为非法,触发错误(详见下文源码解析)。
基础用法示例
文档给出的标准示例——用time.Duration计算一天包含多少秒:
{{ $duration := time.Duration "hour" 24 }} {{ printf "There are %.0f seconds in one day." $duration.Seconds }}渲染结果为:
There are 86400 seconds in one day.这里time.Duration "hour" 24构造了 24 小时的时长,随后调用Duration方法Seconds将其换算为秒数(86400),再通过printf以%.0f格式化输出,避免浮点数小数点后的尾零。
源码实现原理
time.Duration的底层实现在 tpl/time/time.go,逻辑非常清晰,共分三步:
- 单位字符串转换与校验:函数内部维护了一张单位查找表
durationUnits,将每个合法单位(全称与缩写)映射到 Go 标准库的时长常量:
var durationUnits = map[string]time.Duration{ "nanosecond": time.Nanosecond, "ns": time.Nanosecond, "microsecond": time.Microsecond, "us": time.Microsecond, "µs": time.Microsecond, "millisecond": time.Millisecond, "ms": time.Millisecond, "second": time.Second, "s": time.Second, "minute": time.Minute, "m": time.Minute, "hour": time.Hour, "h": time.Hour, }数值转换:通过
cast.ToStringE与cast.ToInt64E完成参数类型转换。这意味着数值参数既可以直接传整数,也可以传数字字符串(如"30"),Hugo 会将其转为int64。乘法构造时长:最终结果由
time.Duration(n) * unitDuration计算得出,即数值乘以单位对应的时长常量。
从源码结构看,time.Duration本质上是「单位查表 + 数值转换 + 标量乘法」的封装,不涉及任何时间基准(如当前时刻或时区),因此它是一个纯函数式的换算工具。
错误处理与边界
当传入非法单位时,函数返回错误:
"%q" is not a valid duration unit例如传入复数形式hours(不在表中)就会触发该错误;tpl/time/time_test.go中的TestDuration用例(tpl/time/time_test.go)明确验证了这一行为,其中{"hours", 20, false}一项断言了非法单位必须返回 error。同一测试还覆盖了全称/缩写/µs变体与字符串数值({"hour", "30", 30 * time.Hour})等 15 组场景,可作为理解函数行为的参考。
与 time.ParseDuration 的对比
time命名空间还提供另一个构造时长的函数time.ParseDuration(文档见 docs/content/en/functions/time/ParseDuration.md,实现见 tpl/time/time.go)。二者都返回time.Duration,但适用场景不同:
| 维度 | time.Duration | time.ParseDuration |
|---|---|---|
| 入参形式 | 独立的单位参数 + 数值参数 | 单个时长字符串,如"300ms"、"-1.5h"、"2h45m" |
| 是否支持组合 | 不支持,一次只能指定一种单位 | 支持,可混合多种单位(如2h45m) |
| 是否支持负数/小数 | 数值可为负(源码未限制),但单位单一 | 支持带符号与小数,如-1.5h |
| 实现方式 | 查表乘法 | 直接调用 Go 标准库time.ParseDuration |
典型场景:若数据源分别给出「单位」和「数量」两个字段(例如配置项拆分为unit: hour与value: 24),用time.Duration更自然;若数据源直接给出一段可读时长字符串,则用time.ParseDuration更直接。
Duration 方法:让返回值发挥作用
time.Duration的返回值可以调用Duration命名空间下的全部方法(方法清单见 docs/content/en/methods/duration/_index.md),包括:
Seconds:返回以秒计的浮点数(float64),示例见 docs/content/en/methods/duration/Seconds.md,例如time.ParseDuration "3.5h2.5m1.5s"的.Seconds结果为12751.5;Minutes、Hours:分别返回以分钟、小时计的浮点数;Milliseconds、Microseconds、Nanoseconds:返回对应粒度的整数值;Abs:返回绝对值的time.Duration;Round、Truncate:按指定时长粒度进行舍入与截断。
这些方法同样适用于time.Duration的返回值,例如开篇示例中的$duration.Seconds。
实际应用:模板中的典型场景
在真实站点模板中,time.Duration常用于把「数值 + 单位」形式的配置转换为可读时长或进行跨单位换算。例如,从站点参数读取缓存过期时长并格式化为秒:
{{ $ttlValue := site.Params.cacheTTL.value | default 30 }} {{ $ttlUnit := site.Params.cacheTTL.unit | default "minute" }} {{ $ttl := time.Duration $ttlUnit $ttlValue }} {{ printf "Cache TTL is %.0f seconds (%v)." $ttl.Seconds $ttl }}或将时长精确格式化到小时:
{{ $d := time.Duration "minute" 90 }} {{ printf "%v" $d }} <!-- 1h30m0s --> {{ printf "%.1f hours" $d.Hours }} <!-- 1.5 hours -->需要强调的是,time.Duration只负责「构造时长」,不涉及具体时间点;若需要结合当前时刻或特定时区做日期运算,应搭配time.Now、time.AsTime、time.In(实现同见 tpl/time/time.go)等函数使用。
小结
time.Duration以极简的「单位 + 数值」二元入参,复用了 Go 标准库的时长体系,为 Hugo 模板提供了清晰、可读的时长构造方式。理解其单位表(含µs变体)、非法单位报错行为以及与time.ParseDuration的分工,能帮助你在模板中写出既准确又易维护的时间换算代码。
【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考