ARTICLE DETAIL

资讯详情

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

Humanizer 中 IDateTimeOffsetHumanizeStrategy 接口详解:自定义 DateTimeOffset.Humanize 日期人性化策略

Humanizer 中 IDateTimeOffsetHumanizeStrategy 接口详解:自定义 DateTimeOffset.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点击查看免费下载导读IDateTimeOffsetHumanizeStrategy是 Humanizer 中负责把两个DateTimeOffset之间的时间距离翻译成自然语言如 an hour from now、30 minutes ago、yesterday的策略接口。它是DateTimeOffset.Humanize()扩展方法的底层可插拔引擎库内默认提供精确度自适应与精度可控两套内置策略也允许你实现该接口后通过Configurator.DateTimeOffsetHumanizeStrategy全局替换。读完本文你将掌握该接口的签名与语义、两条内置策略的算法差异、如何通过Configurator完成策略注入以及如何编写并注册自己的自定义策略。一、接口定义一份最小而清晰的契约IDateTimeOffsetHumanizeStrategy定义在 src/Humanizer/DateTimeHumanizeStrategy/IDateTimeOffsetHumanizeStrategy.cs整个接口只声明了一个方法namespace Humanizer; /// summary /// Implement this interface to create a new strategy for DateTime.Humanize and hook it in the Configurator.DateTimeOffsetHumanizeStrategy /// /summary public interface IDateTimeOffsetHumanizeStrategy { /// summary /// Calculates the distance of time in words between two provided dates used for DateTimeOffset.Humanize /// /summary string Humanize(DateTimeOffset input, DateTimeOffset comparisonBase, CultureInfo? culture); }方法签名解析参数类型语义inputSystem.DateTimeOffset需要被人性化表述的日期即待描述的时间点comparisonBaseSystem.DateTimeOffset比较基准时间点input相对它计算时间距离cultureSystem.Globalization.CultureInfo?输出文案使用的区域性传null表示使用当前线程的区域性返回值为System.String即 distance of time in words——两个时间点之间距离的文字化描述。为什么使用 DateTimeOffset 而非 DateTime与 IDateTimeHumanizeStrategy针对DateTime相比该接口接收的是DateTimeOffset。DateTimeOffset携带 UTC 偏移量因此即使两个时刻的DateTime部分不同、但对应同一个绝对时间点策略也必须基于偏移量做正确的绝对时间比较。从两个内置实现的源码可以看到它们在委托算法前都会先把input与comparisonBase统一转换到 UTCinput.UtcDateTime/comparisonBase.UtcDateTime这正是为了保证跨时区比较的一致性。二、调用链从扩展方法到策略引擎接口本身不产生输出真正的入口是DateTimeOffset.Humanize()扩展方法定义于 src/Humanizer/DateHumanizeExtensions.cspublic static string Humanize(this DateTimeOffset input, DateTimeOffset? dateToCompareAgainst null, CultureInfo? culture null) { var comparisonBase dateToCompareAgainst ?? DateTimeOffset.UtcNow; return Configurator.DateTimeOffsetHumanizeStrategy.Humanize(input, comparisonBase, culture); }关键调用细节dateToCompareAgainst为null时比较基准自动取DateTimeOffset.UtcNow即距离现在多久比较基准也可显式传入用于任意两个时间点的相对描述最终统一走Configurator.DateTimeOffsetHumanizeStrategy该属性定义于 src/Humanizer/Configuration/Configurator.cspublic static IDateTimeOffsetHumanizeStrategy DateTimeOffsetHumanizeStrategy { get; set; } new DefaultDateTimeOffsetHumanizeStrategy();也就是说默认情况下系统已经装配了DefaultDateTimeOffsetHumanizeStrategy开箱即用同时该属性是可写的这为替换策略提供了唯一官方入口。配套的 nullable 重载DateHumanizeExtensions.cs 还提供了DateTimeOffset?的重载当值为null时返回由 formatter 提供的 never 文案如英文never非空时委托给非空版本。测试 tests/Humanizer.Tests/DateTimeOffsetHumanizeTests.cs 验证了null返回never以及 nullable 与非 nullable 结果一致。三、内置策略一DefaultDateTimeOffsetHumanizeStrategy默认实现位于 src/Humanizer/DateTimeHumanizeStrategy/DefaultDateTimeOffsetHumanizeStrategy.cspublic class DefaultDateTimeOffsetHumanizeStrategy : IDateTimeOffsetHumanizeStrategy { public string Humanize(DateTimeOffset input, DateTimeOffset comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.DefaultHumanize(input.UtcDateTime, comparisonBase.UtcDateTime, culture); }它把两个时间点统一转为 UTC 后委托给内部静态算法类DateTimeHumanizeAlgorithms.DefaultHumanize见 src/Humanizer/DateTimeHumanizeStrategy/DateTimeHumanizeAlgorithms.cs。算法特征分段阈值决策DefaultHumanize使用一组硬编码的时间跨度阈值逐级判断单位处理顺序为毫秒 → 秒 → 分钟 → 小时 → 天 → 周 → 月 → 年其核心分支如下来自源码 L192-L264 500 msTimeUnit.Millisecond输出 now 60 s按秒计 120 s折算为 1 分钟a minute ago 60 min按分钟计 90 min折算为 1 小时 24 h按小时计 48 h按天计跨天场景输出 yesterday/tomorrow 7 d按天计 28 d按周计ts.Days / 728 ~ 30 d若同月则按 1 个月否则仍按天 345 d按月计Floor(TotalDays / 29.5)其余按年计Floor(TotalDays / 365)最小为 1 年。时态过去/未来由input comparisonBase ? Tense.Future : Tense.Past决定源码 L139。四、内置策略二PrecisionDateTimeOffsetHumanizeStrategy精度可控实现位于 src/Humanizer/DateTimeHumanizeStrategy/PrecisionDateTimeOffsetHumanizeStrategy.cs采用 C# 主构造函数语法接收精度参数public class PrecisionDateTimeOffsetHumanizeStrategy(double precision .75) : IDateTimeOffsetHumanizeStrategy { readonly double precision precision; public string Humanize(DateTimeOffset input, DateTimeOffset comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.PrecisionHumanize(input.UtcDateTime, comparisonBase.UtcDateTime, precision, culture); }precision 参数的含义与默认值默认值0.75即文档注释中所说的 default precision 0.75取值范围理论上为(0, 1]区间的近似比例。它不改变单位层级而是决定何时把当前单位向上进位到更高一级的近似程度典型效果精度越接近 1进位越严格结果越粗精度越小越容易进位例如 0.75 时 45 秒即进位为 a minute。底层进位算法内部算法DateTimeHumanizeAlgorithms.PrecisionHumanizeDateTimeHumanizeAlgorithms.cs从最小单位向上逐级近似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;随后按days推算月、年days 30 * precision记为 1 个月days 365 * precision记为 1 年超出部分用Floor(days / 30)或Floor(days / 365)结合精度取整。最终从年 → 月 → 天 → 时 → 分 → 秒 → 毫秒的优先级取第一个非零单位调用formatter.DateHumanize(...)生成文案。测试 tests/Humanizer.Tests/DateTimeHumanizePrecisionStrategyTests.cs 给出了大量precision 0.75下的边界行为样例例如750 ms → one second ago而 749 ms 仍是 now45 秒 → a minute ago44 秒仍是 44 seconds ago45 分钟 → an hour ago18 小时 → yesterday17 小时仍是 17 hours ago23 天 → one month ago9 个月 → one year ago。五、选择策略的实战对比维度DefaultDateTimeOffsetHumanizeStrategyPrecisionDateTimeOffsetHumanizeStrategy精度控制无固定阈值构造函数传入precision默认 0.75单位序列ms/s/min/hour/day/week/month/yearms/s/min/hour/day/month/year无周代表输出yesterday、one week ago45 秒即 a minute ago、18 小时即 yesterday典型场景默认、日志与界面通用需要控制近似粒度如保留更大单位的场景需要说明的是两条内置策略都先把输入转成 UTC 再计算因此在带偏移量的DateTimeOffset上行为一致且跨时区安全。这一事实有测试佐证tests/Humanizer.Tests/DateTimeOffsetHumanizeTests.cs 中的DefaultStrategy_DifferentOffsets用两个偏移量不同的时间点验证输出 30 minutes agoDefaultStrategy_WeekAcrossDifferentOffsets验证跨时区整周输出 one week from nowPrecisionStrategy_DifferentOffsets则验证精度策略在02:00与-05:00两个偏移下的跨时区计算结果。六、如何实现并注册自定义策略步骤 1实现接口仿照内置实现写一个自定义策略类比如始终以天数为粒度using System.Globalization; using Humanizer; public class DayGranularityDateTimeOffsetHumanizeStrategy : IDateTimeOffsetHumanizeStrategy { public string Humanize(DateTimeOffset input, DateTimeOffset comparisonBase, CultureInfo? culture) { var days (int)Math.Round((input - comparisonBase).TotalDays); var formatter Configurator.GetFormatter(culture); // 内部 API示例仅示意 // 实际项目中应使用与内置算法一致的 formatter 调用方式 return days 0 ? today : days 0 ? ${days} day(s) from now : ${Math.Abs(days)} day(s) ago; } }说明Configurator.GetFormatter是程序集内部方法见 Configurator.cs公开 API 下更常见的做法是复用或组合现有算法。若要获得完整的本地化支持建议以DefaultDateTimeOffsetHumanizeStrategy或PrecisionDateTimeOffsetHumanizeStrategy为基础做包装而不是从零生成文案。步骤 2通过 Configurator 注入在应用启动阶段或ModuleInitializer中替换全局策略Configurator.DateTimeOffsetHumanizeStrategy new DayGranularityDateTimeOffsetHumanizeStrategy();替换后所有DateTimeOffset.Humanize()调用都会走新策略无需改动任何调用点——这正是策略模式带来的解耦收益。步骤 3验证行为可仿照 DateTimeOffsetHumanizeTests.cs 编写测试先赋值Configurator.DateTimeOffsetHumanizeStrategy再构造inputTime与baseTime断言输出文案。测试中同时展示了策略粒度差异的经典用例同一组时间点2015-07-05 04:00vs2015-07-05 03:00均零偏移默认策略输出 an hour from now而PrecisionDateTimeOffsetHumanizeStrategy(0.75)在相隔约 23 小时时输出 tomorrow。注意事项替换时机的约束Configurator.DateTimeOffsetHumanizeStrategy的 XML 注释Configurator.cs明确建议该属性只能在应用启动阶段、任何人性化操作发生之前设置一次多线程场景下访问该属性需注意可见性如 volatile 读或适当同步生产应用中应避免在服务开始处理请求后再更改。七、与其他 Humanize 策略的体系关系IDateTimeOffsetHumanizeStrategy是 Humanizer 时间人性化策略家族的一员同族接口还包括IDateTimeHumanizeStrategy针对DateTime.Humanize对应Configurator.DateTimeHumanizeStrategyIDateOnlyHumanizeStrategy 与 ITimeOnlyHumanizeStrategy针对 .NET 6 的DateOnly/TimeOnly对应Configurator.DateOnlyHumanizeStrategy与Configurator.TimeOnlyHumanizeStrategyITimeSpanHumanizeStrategy针对TimeSpan。这些策略共享同一套底层算法DateTimeHumanizeAlgorithms与 formatter 注册表Configurator.Formatters最终文案的本地化由各语言的 formatter 提供仓库 Locales 目录下有 100 余个 yml 语言资源。因此无论选择哪套策略an hour ago / 一小时前 这类文案都会随culture参数或当前线程区域性自动本地化。八、快速验证清单默认开箱即用inputTime.Humanize(baseTime)无需任何配置即走DefaultDateTimeOffsetHumanizeStrategy跨时区正确传入不同偏移量的DateTimeOffset时内置策略会先统一到 UTC 再计算精度可调需要近似粒度时实例化new PrecisionDateTimeOffsetHumanizeStrategy(0.75)并赋值给Configurator.DateTimeOffsetHumanizeStrategy可完全自定义实现IDateTimeOffsetHumanizeStrategy.Humanize(input, comparisonBase, culture)并在应用启动阶段替换本地化透明culture为null时使用当前线程区域性文案自动本地化nullable 语义DateTimeOffset?为null时输出 never。// 完整示例两种内置策略的切换与对比 using Humanizer; using Humanizer.Configuration; var inputTime new DateTimeOffset(2015, 07, 05, 04, 0, 0, TimeSpan.Zero); var baseTime new DateTimeOffset(2015, 07, 05, 03, 0, 0, TimeSpan.Zero); // 默认策略 Configurator.DateTimeOffsetHumanizeStrategy new DefaultDateTimeOffsetHumanizeStrategy(); Console.WriteLine(inputTime.Humanize(baseTime)); // an hour from now // 精度策略默认精度 0.75 Configurator.DateTimeOffsetHumanizeStrategy new PrecisionDateTimeOffsetHumanizeStrategy(); Console.WriteLine(baseTime.Humanize(inputTime)); // an hour ago总结IDateTimeOffsetHumanizeStrategy是 Humanizer 将DateTimeOffset时间距离转化为自然语言的可扩展契约接口极简单一Humanize方法内置实现覆盖默认精确与精度可控两条路线全部通过Configurator.DateTimeOffsetHumanizeStrategy全局装配。理解其签名、默认实现、精度算法的进位规则与替换时机约束你就能在项目中精准控制日期文案的粒度甚至注入完全符合业务语义的自定义策略。赞分享开发工具【免费下载链接】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点击查看免费下载相关推荐vnet.pytorch训练全攻略参数调优、损失函数选择与模型评估实战vnet.pytorch训练全攻略参数调优、损失函数选择与模型评估实战 vnet.pytorch是一个基于PyTorch实现的V Net模型专门用于 vol开发工具kAFL核心组件详解Nyx、QEMU与Redqueen如何协同工作kAFL核心组件详解Nyx、QEMU与Redqueen如何协同工作 想要深入理解kAFL这个强大的虚拟机模糊测试框架吗本文将为你详细解析kAFL的三大核心组Rustful部署与生产环境配置Docker、Nginx反向代理与负载均衡终极指南Rustful部署与生产环境配置Docker、Nginx反向代理与负载均衡终极指南 Rustful是一个轻量级的Rust HTTP框架专为构建高性能Web应后端上一篇用树莓派打造你的专属Android Auto智能车机Crankshaft开源方案完全解析下一篇Parsimmon单元测试全攻略确保你的文本处理功能零bug创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表