免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Hugo 时间函数完全指南:AsTime、Format、In 等 6 大函数用法详解与源码解析

Hugo 时间函数完全指南:AsTime、Format、In 等 6 大函数用法详解与源码解析 Hugo 时间函数完全指南AsTime、Format、In 等 6 大函数用法详解与源码解析【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo本文围绕 Hugo 模板引擎中的time函数族展开系统讲解time.AsTime、time.Format、time.In、time.Now、time.Duration、time.ParseDuration六个函数的签名、参数、返回值、时区处理规则与本地化能力并结合 tpl/time/time.go 等源码揭示其底层实现。读完本文你将能在 Hugo 模板中熟练完成日期时间的解析、格式化、时区换算、本地化输出与时长计算并理解timeZone配置与时区优先级背后的设计逻辑。一、概览Hugo 时间处理的两步走Hugo 提供了一系列 函数 与 方法 用于格式化、本地化、解析、比较和操作日期/时间值。但在对这些值进行任何操作之前字符串形式的日期/时间必须先通过time.AsTime函数转换为 Go 的time.Time值。{{ $t : 2023-10-15T13:18:50-07:00 }} {{ time.AsTime $t }} → 2023-10-15 13:18:50 -0700 PDT (time.Time)一旦得到time.Time值就可以将其传给time.Format进行格式化与本地化传给time.In进行时区换算或直接调用time.Time上的任意 time 方法如.Year、.Weekday、.Unix。二、time.AsTime把字符串解析为 time.Time签名与别名签名time.AsTime INPUT [TIMEZONE]返回类型time.Time别名time在模板中直接写time 2023-10-15等价于time.AsTime从 tpl/time/init.go 可以看到time命名空间同时被注册为可调用函数不传参数时返回命名空间上下文用于访问其它时间函数传 1 个或 2 个参数时则分别调用ctx.AsTime(args[0])与ctx.AsTime(args[0], args[1])。可解析字符串time.AsTime的第一个参数必须是可解析的日期/时间字符串表示。Hugo 官方文档维护了一张常见可解析格式表见 docs/content/en/_common/parsable-date-time-strings.md格式时区2023-10-15T13:18:50-07:00America/Los_Angeles2023-10-15T13:18:50-0700America/Los_Angeles2023-10-15T13:18:50ZEtc/UTC2023-10-15T13:18:50默认Etc/UTC2023-10-15默认Etc/UTC15 Oct 2023默认Etc/UTC注意后三种写法没有携带完整的时区信息会默认落到Etc/UTC时区。这也是为什么处理不完整日期字符串时必须留意timeZone配置或显式传入时区参数。覆盖默认时区与优先级要覆盖默认时区可以在项目配置中设置timeZone也可以给time.AsTime传入第二个参数{{ time.AsTime 15 Oct 2023 America/Los_Angeles }}合法时区列表可能因系统而异但应至少包含UTC、Local以及 IANA 时区数据库 中的任意地点。time.AsTime确定时区的优先级如下日期/时间字符串中自带的时区偏移如-07:00作为第二个参数传入time.AsTime的时区项目配置中指定的时区Etc/UTC时区。这一优先级在 tpl/time/time_test.go 的TestTimeLocation用例中得到了直接印证例如2020-09-23T20:33:44-0700即使显式传入America/New_York或Europe/Oslo结果仍是字符串自带的-0700偏移——字符串内嵌偏移的优先级最高。源码级实现在 tpl/time/time.go 中AsTime的逻辑很直观默认使用命名空间持有的ns.location来自语言/站点配置若提供了第二参数则调用time.LoadLocation加载对应时区最后交给 common/htime/time.go 中的htime.ToTimeInDefaultLocationE完成解析。该辅助函数还兼容AsTimeProvider接口由 go-toml 的LocalDate/LocalDateTime实现解决了 TOML front matter 日期时区名为空的问题issue #8895。三、time.Format格式化与本地化签名与别名签名time.Format LAYOUT INPUT返回类型string别名dateFormat{{ dateFormat Monday, Jan 2, 2006 2015-01-21 }}time.Format既可以直接接收time.Time值也可以接收可解析的字符串{{ $t : time.AsTime 2023-10-15T13:18:50-07:00 }} {{ time.Format 2 Jan 2006 $t }} → 15 Oct 2023{{ $t : 15 Oct 2023 }} {{ time.Format January 2, 2006 $t }} → October 15, 2023与time.AsTime相同time.Format也遵循时区优先级但顺序略不同因为它没有第二参数可用日期/时间字符串中自带的时区偏移项目配置中指定的时区Etc/UTC时区。布局字符串Layout string布局字符串基于 Go 的参考时间描述合法组件年2006 06月Jan January 01 1星期Mon Monday月中的日2 _2 02年中的日__2 002时15 3 03分4 04秒5 05AM/PM 标记PM时区偏移-0700 -07:00 -07 -070000 -07:00:00把布局中的正负号换成Z可以在 UTC 时区输出Z而不是偏移量Z0700 Z07:00 Z07 Z070000 Z07:00:00。一个完整示例{{ $t : 2023-01-27T23:44:58-08:00 }} {{ $t time.AsTime $t }} {{ $t $t.Format Jan 02, 2006 3:04 PM Z07:00 }} {{ $t }} → Jan 27, 2023 11:44 PM -08:00需要特别注意三组容易混淆的概念PST、CET这类是时区缩写不是时区-07:00、01:00这类是时区偏移也不是时区时区是本地时间相同的地理区域例如PST/PDT视夏令时而定缩写对应的时区是America/Los_Angeles。本地化Localizationtime.Format可以把time.Time值本地化为当前语言与区域对应的展示形式。Hugo 通过bep/golocales配置项确定区域设置回退到语言键本身详见 docs/content/en/_common/functions/locales.md。既可以使用上面介绍的布局字符串也可以直接使用下面这些以冒号开头的预置 token。例如{{ .Date | time.Format :date_medium }} → Jan 27, 2023本地化为 en-US 时的结果Token结果:date_fullFriday, January 27, 2023:date_longJanuary 27, 2023:date_mediumJan 27, 2023:date_short1/27/23:time_full11:44:58 pm Pacific Standard Time:time_long11:44:58 pm PST:time_medium11:44:58 pm:time_short11:44 pm本地化为 de-DE 时的结果Token结果:date_fullFreitag, 27. Januar 2023:date_long27. Januar 2023:date_medium27.01.2023:date_short27.01.23:time_full23:44:58 Nordamerikanische Westküsten-Normalzeit:time_long23:44:58 PST:time_medium23:44:58:time_short23:44源码级实现Format在 tpl/time/time.go 中先通过htime.ToTimeInDefaultLocationE把输入统一转换为time.Time再交给ns.timeFormatter.Format。真正的本地化逻辑位于 common/htime/time.go以:开头的布局走golocales翻译器FormatDateFull/FormatTimeMedium等的预置格式分支普通布局则先按 Go 原生布局格式化再把布局中出现的January/Jan、Monday/Mon等月份与星期名替换为golocales提供的本地化名称注意time.Month是 1 起始、月份名切片是 0 起始的细节处理。四、time.In按 IANA 时区换算时间v0.146.0 新增签名签名time.In TIMEZONE INPUT返回类型time.Timetime.In返回给定日期/时间在指定 IANA 时区中的表示时区为空字符串或UTC时返回 UTC 时间时区为Local时返回系统本地时区的时间否则时区必须是合法的 IANA 时区名。{{ $layout : 2006-01-02T15:04:05-07:00 }} {{ $t : time.AsTime 2025-03-31T14:45:00-00:00 }} {{ $t | time.In America/Denver | time.Format $layout }} → 2025-03-31T08:45:00-06:00 {{ $t | time.In Australia/Adelaide | time.Format $layout }} → 2025-04-01T01:15:0010:30 {{ $t | time.In Europe/Oslo | time.Format $layout }} → 2025-03-31T16:45:0002:00注意结果中既有日期跨越Adelaide 已是 4 月 1 日也有夏令时导致的偏移差异Denver 为-06:00——这正是 IANA 时区数据库能正确处理而单纯加减固定偏移做不到的地方。源码级实现与性能设计在 tpl/time/time.go 中In通过ns.cacheIn这一 dynacache 分区缓存time.LoadLocation的结果分区键为/tmpl/time/in权重 30ClearNever避免每次调用都重新加载时区数据库。创建该缓存分区的逻辑见 tpl/time/time.goNew中会检查deps.MemCache是否存在。测试 tpl/time/time_test.go 的TestIn覆盖了America/Denver、Australia/Adelaide、Europe/Oslo、UTC、空字符串以及非法时区名InvalidTimeZoneName返回错误等场景其后的BenchmarkInWithCaching基准测试专门验证了时区加载缓存的性能收益。五、time.Now获取当前时间签名签名time.Now返回类型time.Time别名now例如在 2023 年 10 月 15 日于America/Los_Angeles时区构建站点时{{ time.Now }}会产生一个time.Time值其字符串表示类似2023-10-15 12:59:28.337140706 -0700 PDT m0.041752605要格式化并本地化该值可以把它传给time.Format{{ time.Now | time.Format Jan 2006 }} → Oct 2023因为time.Now返回的是time.Time值所以可以直接链式调用任意 time 方法{{ time.Now.Year }} → 2023 (int) {{ time.Now.Weekday.String }} → Sunday {{ time.Now.Month.String }} → October {{ time.Now.Unix }} → 1697400955 (int64)源码级实现Now在 tpl/time/time.go 中直接返回htime.Now()。而 common/htime/time.go 的实现依赖bep/clocks包的Clock变量——它默认使用系统时钟但 Hugo 支持通过clock标志伪造时间这对测试与可复现构建非常有价值注释明确写道 Use this function to fake time inside hugo。六、time.Duration 与 time.ParseDuration时长计算time.Duration单位 数量签名time.Duration TIME_UNIT NUMBER返回类型time.Duration别名durationtime.Duration返回一个time.Duration值可以配合任意Duration方法如.Seconds、.Hours使用{{ $duration : time.Duration hour 24 }} {{ printf There are %.0f seconds in one day. $duration.Seconds }}渲染结果There are 86400 seconds in one day.时间单位必须是下表之一与 tpl/time/time.go 中的durationUnits映射完全一致时长合法时间单位小时hour,h分钟minute,m秒second,s毫秒millisecond,ms微秒microsecond,us,µs纳秒nanosecond,ns在 tpl/time/time.go 的实现中单位字符串在durationUnits中查找数量通过cast.ToInt64E转为 int64两者相乘得到time.Duration单位非法时会返回形如xxx is not a valid duration unit的错误。time.ParseDuration解析时长字符串签名time.ParseDuration DURATION返回类型time.Duration时长字符串是一串可能带符号的十进制数字序列每段可带小数部分和单位后缀例如300ms、-1.5h或2h45m。合法单位是ns、us或µs、ms、s、m、h。{{ $duration : time.ParseDuration 24h }} {{ printf There are %.0f seconds in one day. $duration.Seconds }}渲染结果There are 86400 seconds in one day.实现上tpl/time/time.go先经cast.ToStringE转为字符串再直接委托给 Go 标准库的time.ParseDuration因此语义与 Go 标准库完全一致。七、timeZone 配置全局默认时区time.AsTime与time.Format在输入字符串未携带时区偏移时都会回落到项目配置中的timeZone设置。该配置项定义于 config/allconfig/allconfig.goTimeZone string注释说明它用于解析不含时区信息的 front matter 日期以及 time 函数其官方文档位于 docs/content/en/configuration/all.mdtimeZonestring用于解析没有时区偏移的日期包括 front matter 日期字段以及传给time.AsTime和time.Format的值的时区。合法值列表可能因系统而异但应包含UTC、Local及 IANA 时区数据库 中的任意地点例如America/Los_Angeles和Europe/Oslo。在 Hugo 中timeZone属于站点级配置且在 config/allconfig/allconfig.go 中会随每个语言配置一起传入langs.NewLanguage因此不同语言可以拥有各自独立的默认时区。当time.AsTime或time.Format的输入字符串既无内嵌偏移、也未显式指定时区时最终解析结果就由该配置决定这也是多语言站点保持时间展示一致性的关键设置。八、实战组合完整示例将上述函数串联起来可以实现按站点时区解析 front matter 日期 → 换算到读者所在时区 → 本地化输出的完整链路{{/* 1. 解析字符串为 time.Time默认时区取自 timeZone 配置 */}} {{ $t : time.AsTime .Params.eventDate }} {{/* 2. 换算到目标 IANA 时区 */}} {{ $t $t | time.In Europe/Oslo }} {{/* 3. 本地化格式化输出跟随站点 locale */}} {{ $t | time.Format :date_long }} → 27. Januar 2023de-DE 时 {{ $t | time.Format January 2, 2006 15:04 }} → January 27, 2023 23:44 {{/* 4. 时长计算距离某个截止时间的剩余秒数 */}} {{ $remaining : time.ParseDuration 48h | time.Duration second | printf %.0f }}九、小结函数作用关键点time.AsTime字符串 →time.Time时区优先级字符串偏移 显式参数 timeZone配置 Etc/UTCtime.Format格式化/本地化time.Time布局字符串基于 Go 参考时间:前缀 token 走 golocales 本地化time.In按 IANA 时区换算v0.146.0 新增时区加载结果被 dynacache 缓存time.Now当前时间返回time.Time可链式调用任意 time 方法底层支持clock伪造时间time.Duration单位 数量 → 时长单位映射见 tpl/time/time.gotime.ParseDuration解析时长字符串语义与 Go 标准库time.ParseDuration一致所有函数的实现都集中在 tpl/time/time.go函数注册、别名time/duration/dateFormat/now与示例映射在 tpl/time/init.go覆盖各种边界场景的测试在 tpl/time/time_test.go。掌握这六个函数即可在 Hugo 模板中自如应对解析、格式化、换算、本地化、时长计算全部时间处理需求。【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表