Humanizer PrecisionTimeOnlyHumanizeStrategy 深度解析:从 precision 参数到时间差近似算法
发布时间:2026/9/26 10:21:10 锦皓数字建站

开发工具【免费下载链接】HumanizerHumanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities项目地址https://gitcode.com/gh_mirrors/hu/Humanizer点击查看免费下载导读本文围绕 Humanizer 2.14.1 API 文档中的PrecisionTimeOnlyHumanizeStrategy类展开深入剖析这套面向 .NET 6TimeOnly类型的精度可调时间差自然语言化方案。读完后你将掌握precision默认值 0.75 的真实语义、Humanize方法的调用契约与参数含义、底层近似进位算法的完整实现逻辑并能通过Configurator.TimeOnlyHumanizeStrategy将该策略接入自己的应用同时理解它与默认策略的取舍关系。类概览一个面向 TimeOnly 的精度型时间差计算器PrecisionTimeOnlyHumanizeStrategy是 Humanizer 中负责把两个时刻之间的距离转换成人类可读句子的计算器之一其特点是基于精度precision的近似计算。API 参考文档给出的类定义为public class PrecisionTimeOnlyHumanizeStrategy : Humanizer.DateTimeHumanizeStrategy.ITimeOnlyHumanizeStrategy对应仓库源码中的实际声明位于 PrecisionTimeOnlyHumanizeStrategy.cs可以看到继承关系直接继承自System.Object没有中间基类接口实现实现ITimeOnlyHumanizeStrategy接口平台约束整个类型被#if NET6_0_OR_GREATER条件编译包裹仅在 .NET 6.0 及更高版本可用——这是因为TimeOnly是 .NET 6 引入的仅表示一天内时间的结构体类型。接口定义位于 ITimeOnlyHumanizeStrategy.cs契约非常精简public interface ITimeOnlyHumanizeStrategy { string Humanize(TimeOnly input, TimeOnly comparisonBase, CultureInfo? culture); }实现该接口即可创建自己的TimeOnly.Humanize策略并通过Configurator.TimeOnlyHumanizeStrategy挂载到全局配置中。构造函数与 precision 参数默认 0.75 的语义API 文档记载构造函数签名为public PrecisionTimeOnlyHumanizeStrategy(double precision0.75);源码中采用的是 C# 主构造函数primary constructor语法public class PrecisionTimeOnlyHumanizeStrategy(double precision .75) : ITimeOnlyHumanizeStrategy { readonly double precision precision; ... }要点如下项目说明参数precision近似的精度approximation 精度类型为System.Double默认值不传参时使用0.75内部存储通过readonly double precision precision;在构造时冻结之后不可变更precision的含义可以理解为当距离攒够某个时间单位的多大比例时就向上进位到下一个更大的单位。比例阈值越高输出越倾向于保留更精细的小单位描述比例阈值越低越容易提前进位输出就越粗略。默认值0.75是一种折中大约过了四分之三就进位。具体的进位规则见下文底层算法一节。Humanizer 还提供了一组同源的精度型策略例如面向DateTime的 PrecisionDateTimeHumanizeStrategy.cs其构造函数签名、默认精度与内部实现委托给DateTimeHumanizeAlgorithms.PrecisionHumanize完全一致只是入参类型不同。Humanize 方法与参数说明API 文档记载的方法签名为public string Humanize(System.TimeOnly input, System.TimeOnly comparisonBase, System.Globalization.CultureInfo culture);源码中的实际签名将culture声明为可空类型且方法体只有一行——直接委托给共享算法public string Humanize(TimeOnly input, TimeOnly comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.PrecisionHumanize(input, comparisonBase, precision, culture);三个参数的职责参数类型含义inputTimeOnly要被人化的目标时刻comparisonBaseTimeOnly比较基准时刻用于计算距离cultureCultureInfo?输出语言与文化格式传null时使用当前线程文化返回值System.String即本地化且人化的两时刻距离描述。例如在 en-US 文化下输出5 hours from now在法语文化下输出demain明天。文档中明确描述该方法Returns localized humanized distance of time between two dates; given a specific precision即输出同时受precision和culture两个维度影响。时态判定距离描述带有将来/过去语义。在算法内部DateTimeHumanizeAlgorithms.cspublic static string PrecisionHumanize(TimeOnly input, TimeOnly comparisonBase, double precision, CultureInfo? culture) { var ts new TimeSpan(Math.Abs(comparisonBase.Ticks - input.Ticks)); var tense input comparisonBase ? Tense.Future : Tense.Past; return PrecisionHumanize(ts, tense, precision, culture); }取两个时刻Ticks之差的绝对值构造TimeSpan距离本身不带方向input comparisonBase时tense Future输出形如 from now否则tense Past输出形如 agoTimeOnly只包含一天内的时间分量因此理论最大距离不超过 24 小时。底层算法PrecisionHumanize 的近似与进位逻辑这是本文最核心的部分。DateTimeHumanizeAlgorithms中的私有重载DateTimeHumanizeAlgorithms.cs完整实现了从小单位向大单位逐级近似的流程。第一步逐级向上取整int seconds ts.Seconds, minutes ts.Minutes, hours ts.Hours, days ts.Days; int years 0, months 0; // start approximate from smaller units towards bigger ones if (ts.Milliseconds 999 * precision) { seconds 1; } if (seconds 59 * precision) { minutes 1; } if (minutes 59 * precision) { hours 1; } if (hours 23 * precision) { days 1; }这里可以清晰看到precision对进位阈值的作用进位判定阈值公式precision0.75 时precision0.5 时毫秒 ≥ 阈值 → 秒 1999 * precision749.25 ms499.5 ms秒 ≥ 阈值 → 分 159 * precision44.25 s29.5 s分 ≥ 阈值 → 时 159 * precision44.25 min29.5 min时 ≥ 阈值 → 天 123 * precision17.25 h11.5 h可见precision 越小进位越慷慨结果越粗粒度。测试 TimeOnlyHumanizeTests.cs 中用new PrecisionTimeOnlyHumanizeStrategy(0.75)计算 18:10:49 与 13:07:04 的距离约 5 小时 3 分 45 秒因为 45 秒 ≥ 44.25 秒而进位最终输出5 hours from now。第二步月与年的近似// month calculation if (days 30 * precision days 31) { months 1; } if (days 31 days 365 * precision) { var factor Convert.ToInt32(Math.Floor((double)days / 30)); months days 30 * (factor precision) ? factor 1 : factor; } // year calculation if (days 365 * precision days 366) { years 1; } if (days 365) { var factor Convert.ToInt32(Math.Floor((double)days / 365)); years days 365 * (factor precision) ? factor 1 : factor; }月按 30 天估算年按 365 天估算采用基础因子 precision 余量决定是否再加一档注意TimeOnly距离最多 24 小时月/年分支在TimeOnly场景下永远不会命中这些分支主要服务于同算法的DateTime/DateOnly版本——从源码结构看这是算法被多类型复用的证据。第三步从大到小选取最大非零单位输出var formatter Configurator.GetFormatter(culture); if (years 0) return formatter.DateHumanize(TimeUnit.Year, tense, years); if (months 0) return formatter.DateHumanize(TimeUnit.Month, tense, months); if (days 0) return formatter.DateHumanize(TimeUnit.Day, tense, days); if (hours 0) return formatter.DateHumanize(TimeUnit.Hour, tense, hours); if (minutes 0) return formatter.DateHumanize(TimeUnit.Minute, tense, minutes); if (seconds 0) return formatter.DateHumanize(TimeUnit.Second, tense, seconds); return formatter.DateHumanize(TimeUnit.Millisecond, tense, 0);输出采用只讲最大单位策略只要某个大单位非零就不再提更小的单位全部为零时输出TimeUnit.Millisecond的零值描述各语言的 now/现在 通常来自这里文案的实际生成依赖Configurator.GetFormatter(culture)解析出的语言格式化器因此同一距离在不同文化下会得到完全不同的表达。与默认策略的对比什么时候选 PrecisionHumanizer 为TimeOnly提供了两套内置策略维度DefaultTimeOnlyHumanizeStrategyPrecisionTimeOnlyHumanizeStrategy实现位置DefaultTimeOnlyHumanizeStrategy.csPrecisionTimeOnlyHumanizeStrategy.cs算法DefaultHumanize基于一系列固定阈值分档如 120s → 1 minute、90min → 1 hour、48h → 1 dayPrecisionHumanize基于precision比例的逐级进位可调参数无precision默认 0.75典型输出12 小时差12 hours from nowprecision0.5 时进位为demain1 天后默认策略的完整分档逻辑见 DateTimeHumanizeAlgorithms.cs它内置了sameMonth、days等针对日期场景的额外信息而在TimeOnly重载中固定传入sameMonth: true, days: 0因为纯时间没有日期分量。选型建议追求所见即所得的精确时间差如4 hours ago→ 默认策略或高 precision 值希望输出更大而化之、贴近口语习惯如 11.5 小时就说明天→ 调低 precision 值需要跨策略统一的行为边界、可复现的近似规则 → 使用 Precision 系列并显式指定precision。接入与配置替换 Configurator.TimeOnlyHumanizeStrategyTimeOnly.Humanize的入口在 DateHumanizeExtensions.cspublic static string Humanize(this TimeOnly input, TimeOnly? timeToCompareAgainst null, bool useUtc true, CultureInfo? culture null) { var comparisonBase timeToCompareAgainst ?? TimeOnly.FromDateTime(useUtc ? DateTime.UtcNow : DateTime.Now); return Configurator.TimeOnlyHumanizeStrategy.Humanize(input, comparisonBase, culture); }不传timeToCompareAgainst时以当前时刻为基准useUtc默认true取 UTC最终委托给全局属性Configurator.TimeOnlyHumanizeStrategy其默认值是DefaultTimeOnlyHumanizeStrategy见 Configurator.cs。要在应用中使用精度策略只需在启动阶段替换该全局属性using Humanizer; using Humanizer.Configuration; using Humanizer.DateTimeHumanizeStrategy; // 替换全局 TimeOnly 人化策略precision 按需调整 Configurator.TimeOnlyHumanizeStrategy new PrecisionTimeOnlyHumanizeStrategy(0.75); // 之后所有 TimeOnly.Humanize 调用都会走精度算法 var distance new TimeOnly(18, 10, 49).Humanize(new TimeOnly(13, 07, 04)); // en-US 下输出: 5 hours from now // 也可以绕过全局配置直接用策略实例计算 var result new PrecisionTimeOnlyHumanizeStrategy(0.5) .Humanize(new TimeOnly(13, 08, 05), new TimeOnly(1, 08, 05), CultureInfo.GetCultureInfo(fr)); // 法语下输出: demain12 小时差在 0.5 精度下进位为 1 天注意事项配置时机Configurator中所有策略属性都应在应用启动阶段、任何 humanization 操作发生之前设置一次生产环境不要在请求处理过程中动态修改Configurator.cs 的注释明确了这一线程安全约定可空重载TimeOnly?为null时Humanize返回格式化器的never文案DateHumanizeExtensions.cs这在可选时间字段展示场景很常用文化参数culture传null时使用当前线程文化测试 TimeOnlyHumanizeTests.cs 验证了显式指定文化时输出与对应DateHumanize格式化器一致。测试与行为验证仓库测试 TimeOnlyHumanizeTests.cs 提供了可直接对照的行为基准PrecisionStrategy_NextDayL90-L101new PrecisionTimeOnlyHumanizeStrategy(0.75)计算 18:10:49 与 13:07:04 →5 hours from now验证 45 秒在 0.75 精度下进位为 1 分钟StrategiesAreIsolatedAcrossParallelCulturesL33-L76new PrecisionTimeOnlyHumanizeStrategy(0.5)在法语文化下计算 12 小时差 →demain验证 12h ≥ 23×0.511.5h 进位为 1 天同时验证不同策略在并行多文化场景下彼此隔离DefaultStrategy_SameTimeL9-L18相同时刻 →nowDefaultStrategy_HoursAgoL79-L8813:07:02 相对 17:07:05 →4 hours ago过去时态。这些用例同时印证了距离 时态 文化 precision四个维度的组合行为可作为你集成时的手工验证样例。使用限制与注意事项平台限制PrecisionTimeOnlyHumanizeStrategy仅在NET6_0_OR_GREATER下编译可用面向 .NET Framework / .NET Standard 旧目标的程序无法使用TimeOnly相关 APIprecision 取值范围从算法阈值999*precision、59*precision等公式可以推断precision设计为 (0, 1] 区间内的比例值0.75 是官方默认1 表示凑满整单位才进位趋近 0 表示几乎立即进位到最大单位TimeOnly 的语义边界TimeOnly无日期分量月/年进位分支在纯时间场景不会触发若需跨天甚至跨年的距离人化请使用DateTime/DateOnly的对应策略如PrecisionDateTimeHumanizeStrategy全局替换的影响范围更换Configurator.TimeOnlyHumanizeStrategy会影响应用中所有TimeOnly.Humanize调用点务必在启动期完成替换避免运行期竞态文档与源码的差异API 参考文档中culture参数标注为非空CultureInfo实际源码签名是可空CultureInfo?传null时回退到当前线程文化——以源码行为为准。至此你已完整掌握PrecisionTimeOnlyHumanizeStrategy的类结构、precision参数语义、Humanize调用契约、底层近似算法与接入方式可以按需在项目中定制精度可控、文化自适应的时间差展示逻辑。赞分享开发工具【免费下载链接】HumanizerHumanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities项目地址https://gitcode.com/gh_mirrors/hu/Humanizer点击查看免费下载相关推荐Humanizer 日期时间人性化策略解析从 Default 到 Precision 的可配置相对时间算法Humanizer 日期时间人性化策略解析从 Default 到 Precision 的可配置相对时间算法 本文系统讲解 .NET 库 Humanizer 中开发工具Humanizer PrecisionTimeOnlyHumanizeStrategy 详解用精度参数控制 TimeOnly 时间距离的人性化输出Humanizer PrecisionTimeOnlyHumanizeStrategy 详解用精度参数控制 TimeOnly 时间距离的人性化输出 本指南围绕开发工具Humanizer 中 PrecisionTimeOnlyHumanizeStrategy 精度式时间人性化策略详解Humanizer 中 PrecisionTimeOnlyHumanizeStrategy 精度式时间人性化策略详解 在 .NET 应用里把 TimeOnly开发工具上一篇高效文档下载自动化kill-doc浏览器脚本让免费文档下载如此简单下一篇htop 的 NetBSD 支持实现基于 kvm(3)/sysctl(3) 的进程采集与 curses 库选择机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。