ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Humanizer 的 IDateTimeHumanizeStrategy:深入解析 DateTime.Humanize 可插拔策略接口

Humanizer 的 IDateTimeHumanizeStrategy:深入解析 DateTime.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点击查看免费下载IDateTimeHumanizeStrategy是 Humanizer 中负责把两个DateTime之间的时间距离转化为自然语言句子的策略接口所有DateTime.Humanize()调用最终都会委托给挂载在Configurator.DateTimeHumanizeStrategy上的某个实现。本文以该接口为核心结合仓库源码与测试说明接口契约、内置的默认与精度策略实现、底层算法、注册与切换方式以及如何编写并挂载自定义策略帮助你完全掌控 Humanizer 相对时间表达的生成逻辑。接口定义与契约IDateTimeHumanizeStrategy定义在 src/Humanizer/DateTimeHumanizeStrategy/IDateTimeHumanizeStrategy.cs完整声明如下namespace Humanizer; /// summary /// Implement this interface to create a new strategy for DateTime.Humanize and hook it in the Configurator.DateTimeHumanizeStrategy /// /summary public interface IDateTimeHumanizeStrategy { /// summary /// Calculates the distance of time in words between two provided dates used for DateTime.Humanize /// /summary string Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture); }接口只有一个方法Humanize契约要点如下参数类型含义inputSystem.DateTime要被人类化的目标日期comparisonBaseSystem.DateTime比较基准日期通常为现在cultureSystem.Globalization.CultureInfo?本地化文化信息传入null表示使用当前线程文化返回值System.String两个日期之间时间距离的文字表述从方法签名可以看出Humanizer 把相对时间表述抽象成一次纯粹的距离计算 本地化格式化策略只负责根据两个时刻计算出一个语义化结果具体是现在2 分钟前下个月还是其他说法取决于策略算法与所选文化的格式化器。XML 文档注释同时明确了该接口的设计意图——实现它即可为DateTime.Humanize创建新策略并挂载到Configurator.DateTimeHumanizeStrategy详见下文策略挂载点一节。策略挂载点Configurator.DateTimeHumanizeStrategy接口注释中提到的挂载点位于 src/Humanizer/Configuration/Configurator.cs其声明如下/// summary /// The strategy to be used for DateTime.Humanize /// /summary public static IDateTimeHumanizeStrategy DateTimeHumanizeStrategy { get; set; } new DefaultDateTimeHumanizeStrategy();值得注意的几点默认实现该属性默认初始化为new DefaultDateTimeHumanizeStrategy()即你不做任何配置时DateTime.Humanize就走默认策略。静态可变DateTimeHumanizeStrategy是静态属性可在应用启动阶段替换为任何自定义实现。线程安全要求源码remarks明确要求该属性应只在应用启动时、任何人类化操作发生之前设置一次在多线程场景下访问需要使用 volatile 读取或同步机制生产应用中应避免在服务开始处理请求后修改该值。测试代码 tests/Humanizer.Tests/DateHumanize.cs 也正是通过Configurator.DateTimeHumanizeStrategy new PrecisionDateTimeHumanizeStrategy(precision.Value)/new DefaultDateTimeHumanizeStrategy()来切换两种策略的。调用链从 DateTime.Humanize 到策略接口本身不直接暴露给用户真正被调用的是DateHumanizeExtensions中的扩展方法。在 src/Humanizer/DateHumanizeExtensions.cs 中DateTime.Humanize的完整实现为public static string Humanize(this DateTime input, bool? utcDate null, DateTime? dateToCompareAgainst null, CultureInfo? culture null) { var comparisonBase dateToCompareAgainst ?? DateTime.UtcNow; utcDate ?? input.Kind ! DateTimeKind.Local; comparisonBase utcDate.Value ? comparisonBase.ToUniversalTime() : comparisonBase.ToLocalTime(); return Configurator.DateTimeHumanizeStrategy.Humanize(input, comparisonBase, culture); }这条调用链揭示了几个重要事实当未显式传入dateToCompareAgainst时默认以DateTime.UtcNow为比较基准utcDate参数null时取input.Kind ! DateTimeKind.Local决定基准时刻被转换为 UTC 还是本地时间避免DateTimeKind差异导致的比较错误最终一行把三个参数input、comparisonBase、culture直接转交给Configurator.DateTimeHumanizeStrategy.Humanize——这正是接口契约的调用现场也解释了为什么实现该接口 替换该属性即可完整接管相对时间输出可空版本DateTime?.Humanize()在值为null时不会走策略而是直接返回文化相关的DateHumanize_Never()通常为 never见同一文件 src/Humanizer/DateHumanizeExtensions.cs。此外DateTimeOffset.Humanize走的是同族接口IDateTimeOffsetHumanizeStrategy其默认实现 src/Humanizer/DateTimeHumanizeStrategy/DefaultDateTimeOffsetHumanizeStrategy.cs 内部会把两个DateTimeOffset统一转成UtcDateTime后复用同一套默认算法可见策略族之间存在明显的代码复用设计。内置实现之一DefaultDateTimeHumanizeStrategy默认策略类位于 src/Humanizer/DateTimeHumanizeStrategy/DefaultDateTimeHumanizeStrategy.cs实现非常薄public class DefaultDateTimeHumanizeStrategy : IDateTimeHumanizeStrategy { public string Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.DefaultHumanize(input, comparisonBase, culture); }真正的算法在静态类DateTimeHumanizeAlgorithmssrc/Humanizer/DateTimeHumanizeStrategy/DateTimeHumanizeAlgorithms.cs中。DefaultHumanize先计算时态与时间差var tense input comparisonBase ? Tense.Future : Tense.Past; var ts new TimeSpan(Math.Abs(comparisonBase.Ticks - input.Ticks)); var sameMonth comparisonBase.Date.AddMonths(tense Tense.Future ? 1 : -1) input.Date; var days Math.Abs((input.Date - comparisonBase.Date).Days); return DefaultHumanize(ts, sameMonth, days, tense, culture);随后按时间差落入的区间选择时间单位核心分段规则摘录自DefaultHumanize(TimeSpan, bool, int, Tense, CultureInfo)的if链如下时间差条件输出单位TotalMilliseconds 500TimeUnit.Millisecond量词 0nowTotalSeconds 60TimeUnit.SecondTotalSeconds 120TimeUnit.Minute量词 1a minuteTotalMinutes 60TimeUnit.MinuteTotalMinutes 90TimeUnit.Hour量词 1an hourTotalHours 24TimeUnit.HourTotalHours 48TimeUnit.DayTotalDays 7TimeUnit.DayTotalDays 28TimeUnit.WeekTotalDays 在 [28, 30)若同月输出TimeUnit.Month量词 1否则输出TimeUnit.DayTotalDays 345TimeUnit.Month量词为Floor(TotalDays / 29.5)其余TimeUnit.Year量词为Floor(TotalDays / 365)至少为 1最终统一通过Configurator.GetFormatter(culture).DateHumanize(timeUnit, tense, unit)生成本地化文案即把时间和量词交给文化对应的格式化器因此默认策略天然支持全部已覆盖文化的相对时间表达。内置实现之二PrecisionDateTimeHumanizeStrategy精度策略类位于 src/Humanizer/DateTimeHumanizeStrategy/PrecisionDateTimeHumanizeStrategy.cs是默认策略的近似精度版public class PrecisionDateTimeHumanizeStrategy(double precision .75) : IDateTimeHumanizeStrategy { readonly double precision precision; public string Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.PrecisionHumanize(input, comparisonBase, precision, culture); }构造函数参数precision为近似精度默认0.75源码remarks明确说明若未提供将使用 0.75 作为默认精度。API 文档页 Humanizer.PrecisionDateTimeHumanizeStrategy.md 中记录的签名即为public PrecisionDateTimeHumanizeStrategy(double precision 0.75)。算法差异对应算法PrecisionHumanize在 src/Humanizer/DateTimeHumanizeStrategy/DateTimeHumanizeAlgorithms.cs 中先按precision做进位式近似例如ts.Milliseconds 999 * precision则秒数加 1、seconds 59 * precision则分钟加 1……再做月、年推算最后从大到小选择首个非零时间单位输出。这种设计让使用者可以通过调节precision控制何时向上取整到下一个单位。精度策略的典型行为可以通过测试直观验证。tests/Humanizer.Tests/DateTimeHumanizePrecisionStrategyTests.cs 在UseCulture(en-US)与默认精度0.75下断言749 毫秒 → now750 毫秒 → one second ago临界点由999 * 0.75 ≈ 749.25决定44 秒 → 44 seconds ago45 秒 → a minute ago59 * 0.75 44.25处进位44 分钟 → 44 minutes ago45 分钟 → an hour ago17 小时 → 17 hours ago18 小时 → yesterday42 小时 → 2 days ago。对比默认策略 tests/Humanizer.Tests/DateHumanize.cs 与 tests/Humanizer.Tests/DateHumanizeDefaultStrategyTests.cs可以看到两种策略在边界处的取舍不同默认策略偏向整单位直觉如 45 秒进分钟、90 分钟进小时、48 小时进天精度策略则完全由precision参数驱动。编写并挂载自定义策略基于接口契约自定义策略只需实现Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture)。一个完整可运行的示例using System.Globalization; using Humanizer; public sealed class CustomDateTimeHumanizeStrategy : IDateTimeHumanizeStrategy { public string Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture) { var delta comparisonBase - input; return delta.TotalDays switch { 1 delta.Hours 1 ? just now : ${delta.Hours} hour(s) ago, 7 ${delta.Days} day(s) ago, 30 ${delta.Days / 7} week(s) ago, 365 ${delta.Days / 30} month(s) ago, _ ${delta.Days / 365} year(s) ago }; } }在应用启动阶段如Program.Main、Startup或ModuleInitializer挂载Configurator.DateTimeHumanizeStrategy new CustomDateTimeHumanizeStrategy();之后所有DateTime.Humanize()调用都会自动走自定义逻辑。若只想微调近似程度而不替换整个策略则使用内置的PrecisionDateTimeHumanizeStrategy即可Configurator.DateTimeHumanizeStrategy new PrecisionDateTimeHumanizeStrategy(precision: 0.9);需要强调的约束来自 src/Humanizer/Configuration/Configurator.cs 的remarks由于该属性是进程级静态状态且被扩展方法直接读取务必在应用启动早期、任何Humanize调用发生之前完成设置并在多线程场景下注意可见性与同步生产环境不应在运行中反复变更。策略族全景与延伸阅读IDateTimeHumanizeStrategy并非孤立存在Humanizer 为不同日期时间类型建立了平行的策略族它们共享同一套DateTimeHumanizeAlgorithms核心算法DateTime→IDateTimeHumanizeStrategy本文主题默认DefaultDateTimeHumanizeStrategy精度版PrecisionDateTimeHumanizeStrategy均位于 src/Humanizer/DateTimeHumanizeStrategy/DateTimeOffset→IDateTimeOffsetHumanizeStrategy默认实现复用DateTimeHumanizeAlgorithms.DefaultHumanize(input.UtcDateTime, comparisonBase.UtcDateTime, culture)DateOnly、TimeOnly.NET 6 条件编译NET6_0_OR_GREATER→ 各自的IDateOnlyHumanizeStrategy、ITimeOnlyHumanizeStrategy对应挂载点Configurator.DateOnlyHumanizeStrategy、Configurator.TimeOnlyHumanizeStrategy。也就是说掌握了IDateTimeHumanizeStrategy的接口 → 挂载点 → 扩展方法 → 算法 → 文化格式化器这条链路就能举一反三理解整个 Humanizer 日期人类化体系的扩展方式。更多背景可参考 ARCHITECTURE.md 与 API 文档目录 website/versioned_docs/version-3.0.8/api/其中包含 Humanizer.DefaultDateTimeHumanizeStrategy.md 与 Humanizer.PrecisionDateTimeHumanizeStrategy.md 的完整 API 记录。赞分享开发工具【免费下载链接】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 IDateTimeHumanizeStrategy 接口定制 DateTime.Humanize 的相对时间转换策略Humanizer IDateTimeHumanizeStrategy 接口定制 DateTime.Humanize 的相对时间转换策略 Humanizer开发工具Humanizer 中 IDateTimeHumanizeStrategy 接口详解自定义 DateTime.Humanize 相对时间策略Humanizer 中 IDateTimeHumanizeStrategy 接口详解自定义 DateTime.Humanize 相对时间策略 IDateTim开发工具深入解析 Humanizer 的 IDateTimeHumanizeStrategy自定义 DateTime.Humanize 相对时间策略深入解析 Humanizer 的 IDateTimeHumanizeStrategy自定义 DateTime.Humanize 相对时间策略 本指南围绕 Hu开发工具上一篇HTTrack安全实践指南7个关键步骤避免网站镜像风险与陷阱下一篇ta-lib-python性能优化案例从2秒到200毫秒创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表