
开发工具【免费下载链接】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点击查看免费下载DefaultDateOnlyHumanizeStrategy是 Humanizer 为 .NET 6 引入的DateOnly类型提供的默认“时间距离转文字”计算器。当你在代码里调用someDate.Humanize()得到3 days ago、one month from now这样的自然语言表达时背后正是该策略在起作用。本文将结合仓库源码与测试完整剖析这个类的定位、Humanize方法的调用约定、默认分级算法、文化本地化机制以及自定义替换方式帮助你理解并能灵活运用 Humanizer 的日期人性化体系。类定位一个实现IDateOnlyHumanizeStrategy的默认策略DefaultDateOnlyHumanizeStrategy是 Humanizer 针对DateOnly类型仅日期、无时间部分的“距离转文字”默认实现定义在 src/Humanizer/DateTimeHumanizeStrategy/DefaultDateOnlyHumanizeStrategy.cspublic class DefaultDateOnlyHumanizeStrategy : IDateOnlyHumanizeStrategy { /// summary /// Calculates the distance of time in words between two provided dates /// /summary public string Humanize(DateOnly input, DateOnly comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.DefaultHumanize(input, comparisonBase, culture); }从中可以看到几个关键信息继承关系直接继承System.Object实现了 IDateOnlyHumanizeStrategy 接口该接口是 Humanizer 定义“日期人性化策略”的统一契约目标框架限制整个文件被#if NET6_0_OR_GREATER条件编译指令包裹——因为DateOnly是 .NET 6 引入的类型所以该策略仅在 .NET 6 及更高版本中生效早于 .NET 6 的 TFM 下类不存在实现极简类的全部职责是委托——把Humanize调用转交给内部静态算法类DateTimeHumanizeAlgorithms.DefaultHumanize(input, comparisonBase, culture)自身不包含任何格式化逻辑这也符合策略模式的职责划分。接口契约三个参数的含义IDateOnlyHumanizeStrategy定义了唯一的抽象方法string Humanize(DateOnly input, DateOnly comparisonBase, CultureInfo? culture);参数类型含义inputSystem.DateOnly需要被人性化的目标日期comparisonBaseSystem.DateOnly比较基准日期距离由input相对comparisonBase计算cultureSystem.Globalization.CultureInfo?用于本地化输出的文化传null表示使用当前线程文化返回值是string——一段本地化、可读的相对时间短语。接口的语义注释明确指出实现该接口即可创建DateOnly.Humanize的新策略并可挂载到Configurator.DateOnlyHumanizeStrategy上替换默认行为见 IDateOnlyHumanizeStrategy.cs。默认算法内部实现从日期差到自然语言的分级流水线DefaultDateOnlyHumanizeStrategy委托的核心是DateTimeHumanizeAlgorithms.DefaultHumanize(DateOnly, DateOnly, CultureInfo)位于 src/Humanizer/DateTimeHumanizeStrategy/DateTimeHumanizeAlgorithms.cs。它先把两个日期规整为TimeSpan距离再走一条统一的分级判断流水线public static string DefaultHumanize(DateOnly input, DateOnly comparisonBase, CultureInfo? culture) { if (input comparisonBase) { return DateOnlyHumanizeToday(culture); } var tense input comparisonBase ? Tense.Future : Tense.Past; var diffDays Math.Abs(comparisonBase.DayNumber - input.DayNumber); var ts new TimeSpan(diffDays, 0, 0, 0); var sameMonth comparisonBase.AddMonths(tense Tense.Future ? 1 : -1) input; var days Math.Abs(input.DayNumber - comparisonBase.DayNumber); return DefaultHumanize(ts, sameMonth, days, tense, culture); }特殊分支同日返回 “today”当input comparisonBase时算法直接调用DateOnlyHumanizeToday(culture)DateTimeHumanizeAlgorithms.cs。该辅助方法先请求 formatter 输出“毫秒级、过去时、数量 0”的基础短语如now再通过DefaultFormatter.DateHumanize_Today做一次等价替换若基础短语仍是now就替换为本地化的today若自定义 formatter 改写了now的措辞则保留自定义结果见 DefaultFormatter.cs。测试 DateOnlyHumanizeTests.cs 中的TodayWording_PreservesCustomDateHumanizeOverride专门验证了这一“保留自定义覆盖”行为。时态判定与距离计算时态Tenseinput comparisonBase表示未来如 “in 2 days”否则为过去如 “2 days ago”。Tense枚举定义见 src/Humanizer/Localisation/Tense.cs注释中分别给出 “in 2 days” 与 “2 days ago” 两个典型示例天数距离借助DateOnly.DayNumber自 0001-01-01 起的天数序号做纯算术差值再用TimeSpan(diffDays, 0, 0, 0)构造时间跨度避免DateTime常见的时分秒干扰同月判定sameMonth用于 28–30 天区间的特殊措辞选择见下文。分级输出毫秒到年的完整桶bucket规则DefaultHumanize(TimeSpan, bool, int, Tense, CultureInfo)DateTimeHumanizeAlgorithms.cs是一串自小而大的边界判断落到第一个命中档位即返回距离区间输出单位数量 500msMillisecond0即 “now” 60sSecondts.Seconds 120sMinute1“一分钟” 60minMinutets.Minutes 90minHour1 24hHourts.Hours 48hDay由日期差算出的days 7dDayts.Days 28dWeekts.Days / 728d – 30dMonth同月或 Day跨月1 /ts.Days 345dMonthMath.Floor(ts.TotalDays / 29.5) 345dYearMath.Floor(ts.TotalDays / 365)最小为 1值得注意的两个细节28–30 天的“同月歧义”若两个日期相隔 28 至 30 天且处在同一个月内输出 “one month”否则回退为按天输出。例如2015-08-05相对2015-07-05的输出是 “one month from now”见测试DefaultStrategy_MonthApartDateOnlyHumanizeTests.cs按天向上取整逻辑 48h档位输出的是日期差days而非ts.Days——因为DateOnly没有小时分量ts.Days恒等于diffDays此处复用days参数保持了与DateTime版本算法的同构。每个档位最终都调用formatter.DateHumanize(TimeUnit, Tense, count)产出本地化短语TimeUnit枚举涵盖 Millisecond、Second、Minute、Hour、Day、Week、Month、Year 等见 src/Humanizer/Localisation/TimeUnit.cs。文化本地化短语表驱动的输出DefaultHumanize的每个分支都通过Configurator.GetFormatter(culture)获取当前文化的 formatterDateTimeHumanizeAlgorithms.cs默认实现是DefaultFormattersrc/Humanizer/Localisation/Formatters/DefaultFormatter.cs。DefaultFormatter的DateHumanize方法会从生成的语言短语表LocalePhraseTable由 Humanizer.SourceGenerators 依据 src/Humanizer/Locales 下的 yml 文件生成中解析对应TimeUnit Tense的短语模板再处理单复数Singular/Multiple、数量占位符与语法格。测试Humanize_UsesSpecifiedCultureDateOnlyHumanizeTests.cs验证了跨语言场景baseDate.AddDays(-1).Humanize(baseDate, culture)会按传入文化输出“昨天”的本地化措辞且与Configurator.GetFormatter(culture)直接输出的短语保持一致。SameDate_UsesDateOnlyWordingWithoutChangingCultureFallback测试则验证了 en-GB 输出today、fr-FR 输出maintenantDateOnlyHumanizeTests.cs。如何调用Humanize 扩展方法的完整链路DefaultDateOnlyHumanizeStrategy不会直接被业务代码调用而是经由 DateHumanizeExtensions.cs 的扩展方法间接使用public static string Humanize(this DateOnly input, DateOnly? dateToCompareAgainst null, CultureInfo? culture null) { var comparisonBase dateToCompareAgainst ?? DateOnly.FromDateTime(DateTime.UtcNow); return Configurator.DateOnlyHumanizeStrategy.Humanize(input, comparisonBase, culture); }默认基准不传dateToCompareAgainst时以DateTime.UtcNow转换出的当天日期为基准因此DateOnly.FromDateTime(DateTime.Now).Humanize()通常输出 “today”策略来源调用链上真正执行的是Configurator.DateOnlyHumanizeStrategy——该属性的默认值正是new DefaultDateOnlyHumanizeStrategy()见 Configurator.cs可空重载DateOnly?扩展在值为null时直接返回 formatter 的DateHumanize_Never()即 “never”非空时转发给值类型版本DateHumanizeExtensions.cs。实用示例using Humanizer; // 默认基准UTC 今天 var today DateOnly.FromDateTime(DateTime.UtcNow); today.Humanize(); // today // 指定比较基准 new DateOnly(2015, 7, 2).Humanize(new DateOnly(2015, 7, 5)); // 3 days ago new DateOnly(2015, 8, 5).Humanize(new DateOnly(2015, 7, 5)); // one month from now new DateOnly(2013, 7, 5).Humanize(new DateOnly(2015, 7, 5)); // 2 years ago // 指定文化 new DateOnly(2024, 1, 1).Humanize(new DateOnly(2024, 1, 2), new CultureInfo(fr-FR)); // hier // 可空重载 DateOnly? never null; never.Humanize(); // never前三个断言语义与仓库测试DefaultStrategy_SameDate、DefaultStrategy_MonthApart、DefaultStrategy_DaysAgo、DefaultStrategy_YearsAgo完全对应DateOnlyHumanizeTests.cs。自定义与替换何时不再使用默认策略IDateOnlyHumanizeStrategy的另一实现是PrecisionDateOnlyHumanizeStrategysrc/Humanizer/DateTimeHumanizeStrategy/PrecisionDateOnlyHumanizeStrategy.cs它接受一个精度参数默认0.75通过DateTimeHumanizeAlgorithms.PrecisionHumanize按“比例取整”的方式把距离近似到更接近的单位例如相隔 1 天输出 “tomorrow”。两者对比维度DefaultDateOnlyHumanizeStrategyPrecisionDateOnlyHumanizeStrategy构造参数无参double precision .75同日输出“today”走DateOnlyHumanizeToday同样输出 “today”1 天距离“tomorrow”/“yesterday”“tomorrow”/“yesterday” 59 * precision进位计算方式按固定阈值分级秒/分/时/天/周/月/年按精度系数近似取整需要替换默认行为时在应用启动阶段任何人性化调用发生之前给Configurator.DateOnlyHumanizeStrategy赋值即可例如Configurator.DateOnlyHumanizeStrategy new PrecisionDateOnlyHumanizeStrategy(0.75);注意 Configurator.cs 的文档提醒该属性只应在应用启动时设置一次多线程场景下需使用 volatile 读或同步机制生产应用中避免在提供服务后变更。总结与适用边界核心职责DefaultDateOnlyHumanizeStrategy是DateOnly.Humanize()的默认“距离转文字”策略把所有工作委托给DateTimeHumanizeAlgorithms.DefaultHumanize自身保持纯策略壳算法特点同日特判 “today”、按固定阈值分级秒→分→时→天→周→月→年、28–30 天区间依据同月性决定月/天措辞、所有输出经 formatter 本地化版本前提整个类型仅在NET6_0_OR_GREATER下编译DateOnly依赖使用前请确认目标框架为 .NET 6可替换性通过Configurator.DateOnlyHumanizeStrategy可在启动期切换为PrecisionDateOnlyHumanizeStrategy或自定义实现满足不同精度需求。如需深入了解相邻类型可继续阅读 IDateOnlyHumanizeStrategy.cs、PrecisionDateOnlyHumanizeStrategy.cs 与对应测试 DateOnlyHumanizeTests.cs。赞分享开发工具【免费下载链接】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 的 DefaultDateOnlyHumanizeStrategyDateOnly 相对时间人性化默认策略的源码级解析Humanizer 的 DefaultDateOnlyHumanizeStrategyDateOnly 相对时间人性化默认策略的源码级解析 导读 Defaul开发工具Humanizer 的 DefaultDateTimeHumanizeStrategy 深入解析DateTime 相对时间文案的默认策略与算法原理Humanizer 的 DefaultDateTimeHumanizeStrategy 深入解析DateTime 相对时间文案的默认策略与算法原理 Defau开发工具Humanizer 中 DefaultTimeOnlyHumanizeStrategy 源码解读TimeOnly 相对时间人性化的默认策略实现Humanizer 中 DefaultTimeOnlyHumanizeStrategy 源码解读TimeOnly 相对时间人性化的默认策略实现 本文围绕开发工具上一篇Apereo CAS 主身份解析配置详解PersonDirectoryPrincipalResolver 与自定义 PrincipalResolver 实战下一篇微信视频号直播弹幕实时抓取工具轻松获取直播间互动数据的终极方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考