☰
Humanizer 日期人性化资源键机制解析:ResourceKeys.DateHumanize 类深入指南
2026/9/28 21:27:09 网站建设 项目流程
  • 开发工具

【免费下载链接】Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

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

导读

ResourceKeys.DateHumanize是 Humanizer 本地化体系中的一个核心工具类,它按照既定命名约定为DateTime.Humanize(日期人性化)输出生成资源键。理解这一机制,你就能明白 Humanizer 如何把"3 分钟前""2 天后"这样的相对时间短语翻译成 100 多种语言的文案,也能够在自定义 Formatter 或调试本地化问题时直接利用这些键。本文围绕该类展开,结合仓库源码与测试,梳理其字段、方法约定、调用链和自定义实践。

类概览:静态的"键约定"封装

在 version-2.14.1 API 文档 中,该类型被定义为:

public static class ResourceKeys.DateHumanize

它是一个public static class,不继承任何业务基类,继承链仅为System.Object。类的职责正如其 XML 注释所述:"Encapsulates the logic required to get the resource keys for DateTime.Humanize"——即封装为日期人性化获取资源键所需的一切逻辑。

从整体架构看,它位于 Humanizer 本地化(Localisation)子系统的"键生成"层:

  • 消费方:DefaultFormatter等 IFormatter 实现,它们把资源键与具体本地化文本关联;
  • 生成方:ResourceKeys.DateHumanize提供约定式的键字符串;
  • 数据源:各个 Locale 的 YAML 短语表(见 src/Humanizer/Locales)。

字段:两个固定的常量资源键

该类暴露两个public const string字段,它们对应日期人性化中最特殊的两种状态——"从未发生"与"此时此刻":

字段常量值语义
ResourceKeys.DateHumanize.Never"DateHumanize_Never"表示事件从未发生(如null日期)的文案键
ResourceKeys.DateHumanize.Now"DateHumanize_Now"表示当前时刻的文案键

两者的字段类型都是System.String。这两个键在 Humanizer 中形成了稳定的公共契约:IFormatter接口就定义了对应的两个方法DateHumanize_Never()与DateHumanize_Now()(见 IFormatter.cs),DefaultFormatter则在 DefaultFormatter.cs 中实现:

public virtual string DateHumanize_Now() => phraseTable.DateNow ?? "now"; public virtual string DateHumanize_Never() => phraseTable.DateNever ?? "never";

也就是说,键名DateHumanize_Now/DateHumanize_Never与IFormatter的方法名一一对应,这正是"约定"的体现。当某个 Locale 的短语表中缺少对应短语时,DefaultFormatter会回退到英文默认值"now"与"never";多语言实现则由生成的 Locale 短语表提供,例如日语短语表中DateHumanize_Now对应 "今"、泰米尔语对应 "இப்போது"、斯瓦希里语对应 "ugbu a"(见 GeneratedFormatterRuntimeTests.cs)。

方法:GetResourceKey 的约定生成规则

GetResourceKey是类的核心方法,原型为:

public static string GetResourceKey( Humanizer.Localisation.TimeUnit timeUnit, Humanizer.Localisation.Tense timeUnitTense, int count = 1);

三个参数的语义

  • timeUnit(TimeUnit):时间单位枚举,包含Millisecond、Second、Minute、Hour、Day、Week、Month、Year八个取值;
  • timeUnitTense(Tense):时态枚举,Future表示未来(如 "in 2 days"),Past表示过去(如 "2 days ago");
  • count:单位数量,int类型,默认值为 1(文档中注明 "default is One")。

返回值的命名约定

方法返回形如DateHumanize_SingleMinuteAgo的资源键。将返回值反推即可还原出完整的命名规则:

DateHumanize_ + <单复数前缀> + <时间单位> + <时态后缀>

其中:

  • 单复数前缀:count为 1 时使用Single,大于 1 时使用复数形式(如Multiple);
  • 时间单位:取自TimeUnit枚举名(如Minute、Hour、Day);
  • 时态后缀:Tense.Past对应Ago,Tense.Future对应FromNow。

例如GetResourceKey(TimeUnit.Minute, Tense.Past, 1)生成DateHumanize_SingleMinuteAgo;GetResourceKey(TimeUnit.Day, Tense.Future, 5)则会生成类似DateHumanize_MultipleDaysFromNow的键。这种命名约定让每个相对时间短语都拥有稳定、可预测、可调试的标识符,也使得本地化短语表(如 en.yml)中的条目能够按键名自动映射。

在 Humanize 调用链中的位置

要理解ResourceKeys.DateHumanize的价值,需要看清整条相对时间生成链路。以DateTime.Humanize()为例,入口是 DateHumanizeExtensions.cs:

  1. 计算对比基准(默认DateTime.UtcNow),交由Configurator.DateTimeHumanizeStrategy处理;
  2. 策略层(如 DefaultDateTimeHumanizeStrategy)调用 DateTimeHumanizeAlgorithms.cs 中的算法,把时间差换算成"单位 + 时态";
  3. 算法最终调用formatter.DateHumanize(timeUnit, tense, count)(见 DateTimeHumanizeAlgorithms.cs),由DefaultFormatter从短语表取词渲染(DefaultFormatter.cs);
  4. 短语表条目即由GetResourceKey这类约定键进行组织与查找。

特殊情况下,null的DateTime?会走DateHumanize_Never()返回 "never" 类文案(DateHumanizeExtensions.cs),这正是Never字段对应的场景;当时间差不足 500ms 时,算法直接以TimeUnit.Millisecond渲染"此刻"语义(DateTimeHumanizeAlgorithms.cs),对应Now字段的场景。

测试与公共 API 契约

该类型作为公共 API 被 PublicApiApprovalTest 锁定在多个目标框架的 verified 文件中(如 DotNet10_0.verified.txt 中的DateHumanize_Never()与DateHumanize_Now()方法签名),任何签名变更都会在 CI 中被捕获。此外,GeneratedFormatterRuntimeTests.cs 和 CoverageGapTests.cs 会逐一验证各 Locale 的DateHumanize_Now/DateHumanize_Never输出,以及英文回退值"now"、"never",确保"键 → 多语言文案"映射不会出现缺口。

实践要点

  • 调试本地化缺失:当某个语言缺少相对时间短语时,DefaultFormatter会抛出InvalidOperationException,其中包含 Culture 名与单位信息(DefaultFormatter.cs)。此时可利用GetResourceKey生成期望的键,再到 src/Humanizer/Locales 对应 yml 中核对条目是否存在。
  • 扩展自定义 Formatter:若继承DefaultFormatter实现自定义本地化,应遵循DateHumanize_*键名约定命名短语条目,保证与IFormatter接口方法及短语表解析逻辑兼容。
  • 了解回退行为:缺少短语时默认回退英文 "now"/"never",因此对外呈现永远有兜底文案,不会返回空字符串。

小结

ResourceKeys.DateHumanize用两个常量字段与一个静态方法,把DateTime.Humanize的资源键约定固化成了可复用的公共 API:Never/Now覆盖两种特殊状态,GetResourceKey则按"单复数 + 单位 + 时态"的统一约定为常规相对时间生成键。它与IFormatter、DefaultFormatter及 Locale 短语表共同构成了 Humanizer 日期人性化本地化的完整链路,是阅读和扩展该模块时最值得优先理解的入口之一。

  • 开发工具

【免费下载链接】Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

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

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

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

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

立即咨询