首页/新闻资讯/正文详情

Humanizer 相对时间人性化:DefaultDateTimeHumanizeStrategy 默认策略源码级解析

发布时间:2026/9/25 2:38:54 来源:云帆数科 栏目:资讯中心
Humanizer 相对时间人性化:DefaultDateTimeHumanizeStrategy 默认策略源码级解析
开发工具【免费下载链接】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 的DefaultDateTimeHumanizeStrategy是 .NET 平台下将两个DateTime之间的时间距离转换为自然语言如 2 hours ago、tomorrow、one month from now的默认计算策略。本文以该策略的 API 参考文档为核心结合 src/Humanizer/DateTimeHumanizeStrategy/DefaultDateTimeHumanizeStrategy.cs 及配套算法源码、配置入口和测试用例完整讲解它的类结构、方法签名、底层分级算法、时态判断与本地化机制并给出可直接运行的实战示例。读完本文你将能掌握DateTime.Humanize()的默认输出规则、替换为自定义策略的方法以及通过测试数据验证输出结果的具体方式。类定位Humanizer 日期人性化的策略模式入口在 Humanizer 中人性化时间距离distance of time in words并不是硬编码在扩展方法里的而是通过策略模式实现DefaultDateTimeHumanizeStrategy就是这一体系的默认实现。public class DefaultDateTimeHumanizeStrategy : Humanizer.DateTimeHumanizeStrategy.IDateTimeHumanizeStrategy类声明要点命名空间Humanizer.DateTimeHumanizeStrategy继承链System.Object→DefaultDateTimeHumanizeStrategy实现接口IDateTimeHumanizeStrategy该接口只声明了一个方法string Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture)。接口的设计目标见 IDateTimeHumanizeStrategy.cs是允许开发者实现自己的策略并通过Configurator.DateTimeHumanizeStrategy把它挂接到DateTime.Humanize上。也就是说DefaultDateTimeHumanizeStrategy只是 Humanizer 提供给开箱即用的默认答案整个计算链路是开放的、可替换的。策略被挂接的位置在 Configurator.cs默认值正是本类public static IDateTimeHumanizeStrategy DateTimeHumanizeStrategy { get; set; } new DefaultDateTimeHumanizeStrategy();该属性属于Humanizer.Configuration.Configurator静态类因此在实际应用中可以通过一行代码全局替换人性化策略例如Configurator.DateTimeHumanizeStrategy new PrecisionDateTimeHumanizeStrategy(0.75);Humanize 方法签名、参数与返回值文档核心 API 是Humanize(DateTime, DateTime, CultureInfo)方法官方定义为计算两个给定日期之间的时间距离用文字表达。public string Humanize(System.DateTime input, System.DateTime comparisonBase, System.Globalization.CultureInfo culture);参数说明参数类型含义inputSystem.DateTime要被人性化描述的日期即目标时间点comparisonBaseSystem.DateTime比较基准日期即当前时间点cultureSystem.Globalization.CultureInfo用于本地化输出的区域性信息例如en-US、zh-CN、ru-RU返回值System.String一段本地化的自然语言描述例如one year ago、in 2 weeks。实现一行委托给核心算法DefaultDateTimeHumanizeStrategy的源码极其简洁它本身不包含任何计算逻辑而是把工作委托给 DateTimeHumanizeAlgorithms.DefaultHumanizepublic string Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.DefaultHumanize(input, comparisonBase, culture);真正的时间距离换算、时态判定、单位取舍全部发生在DateTimeHumanizeAlgorithms这个静态算法类中。完整调用链从扩展方法到最终输出在实际使用中开发者通常不会直接调用策略的Humanize而是通过扩展方法触发。整条调用链如下入口DateHumanizeExtensions.cs 中的DateTime.Humanize()扩展方法public static string Humanize(this DateTime input, bool? utcDate null, DateTime? dateToCompareAgainst null, CultureInfo? culture null)它负责确定comparisonBase默认取DateTime.UtcNow并根据utcDate参数将基准统一为 UTC 或本地时间然后调用Configurator.DateTimeHumanizeStrategy.Humanize(input, comparisonBase, culture)策略分发Configurator.DateTimeHumanizeStrategy当前指向DefaultDateTimeHumanizeStrategy算法执行DefaultDateTimeHumanizeStrategy.Humanize委托给DateTimeHumanizeAlgorithms.DefaultHumanize本地化输出算法内部通过Configurator.GetFormatter(culture)取得 IFormatter 实例调用formatter.DateHumanize(TimeUnit, Tense, int)拼出最终文本。值得注意的是扩展方法还提供了两个便捷重载见 DateHumanizeExtensions.csDateTime?可空重载输入为null时返回本地化的 never由formatter.DateHumanize_Never()提供显式传入dateToCompareAgainst和culture可在不依赖系统时钟的情况下做确定性测试测试代码正是这样做的。默认算法逐级拆解阈值、时态与单位选择DateTimeHumanizeAlgorithms.DefaultHumanize是整篇文章的核心。它的第一步是计算时态与时间跨度var tense input comparisonBase ? Tense.Future : Tense.Past; var ts new TimeSpan(Math.Abs(comparisonBase.Ticks - input.Ticks));时态input晚于comparisonBase判定为Tense.Future未来否则为Tense.Past过去。两个枚举值的语义见 Tense.csFuture 输出类似 in 2 daysPast 输出类似 2 days ago时间差通过Ticks差取绝对值构造TimeSpan因此算法只关心距离的大小不关心正负方向月份特殊判定sameMonth用于判断input与comparisonBase是否恰好相差一个月考虑未来/过去方向这影响 28~30 天区间内的输出归属。随后进入由小到大、逐级匹配的阈值判断见 DateTimeHumanizeAlgorithms.cs。下表汇总了完整阈值与对应输出单位区间条件输出单位与数量典型输出en-USPastts.TotalMilliseconds 500Millisecond0nowts.TotalSeconds 60Secondts.Seconds10 seconds agots.TotalSeconds 120Minute1a minute agots.TotalMinutes 60Minutets.Minutes44 minutes agots.TotalMinutes 90Hour1an hour agots.TotalHours 24Hourts.Hours10 hours agots.TotalHours 48Daydaysyesterday跨日或 2 days agots.TotalDays 7Dayts.Days6 days agots.TotalDays 28Weekts.Days / 7one week ago、2 weeks ago28 ≤ TotalDays 30若sameMonth为 Month,1否则 Dayone month ago 或按天TotalDays 345Monthfloor(TotalDays / 29.5)10 months ago其余Yearfloor(TotalDays / 365)至少 1one year ago几个值得注意的算法细节一小时边界90 分钟以内一律输出 an hour 而非 1 hour这与英语本地化习惯一致昨天/明天判定TotalHours 48分支使用的是days Math.Abs((input.Date - comparisonBase.Date).Days)即按日历日差值而非按小时数计算所以跨天 1 天输出 yesterday/tomorrow而不是 24 hours ago28~30 天的月份边界sameMonth成立时输出 one month否则输出 N days。测试 TwentyEightDaysUsesCalendarMonth 专门验证了这一点从 2023-03-01 往前 28 天输出 one month ago从 2023-02-01 往后 28 天输出 one month from now年度下限TotalDays / 365计算出的years为 0 时强制置 1避免出现 0 years。最终输出统一调用formatter.DateHumanize(TimeUnit.Year, tense, years);其中TimeUnit枚举Millisecond / Second / Minute / Hour / Day / Week / Month / Year见 TimeUnit.cs数量词的复数形式one second vs 2 seconds由各语言 formatter 内部处理。本地化culture 如何影响最终文案culture参数在算法中并不参与数值计算而是决定选用哪个语言的 formatter。算法内部通过Configurator.GetFormatter(culture)见 Configurator.cs从FormatterRegistry解析出对应文化的IFormatter再由它把(TimeUnit, Tense, count)三元组渲染成本地语言的自然语句。这一机制可以从测试得到直观印证。CanSpecifyCultureExplicitly 展示了同一组数值在不同文化下的输出[InlineData(1, TimeUnit.Year, Tense.Future, en-US, one year from now)] [InlineData(40, TimeUnit.Second, Tense.Past, ru-RU, 40 секунд назад)] [InlineData(2, TimeUnit.Day, Tense.Past, sv-SE, för 2 dagar sedan)] [InlineData(2, TimeUnit.Week, Tense.Future, de-DE, in 2 Wochen)]如果调用时不传culture传nullHumanizer 将使用当前线程的CurrentCulture。完整的本地化文案由各语言的.yml语言资源文件维护见 src/Humanizer/Locales 下的en.yml、ru.yml、de.yml等并由 SourceGenerator 在编译期生成对应的 Formatter 类型。与 PrecisionDateTimeHumanizeStrategy 的对比理解默认策略的最佳参照系是同接口的另一个实现 PrecisionDateTimeHumanizeStrategypublic class PrecisionDateTimeHumanizeStrategy(double precision .75) : IDateTimeHumanizeStrategy { public string Humanize(DateTime input, DateTime comparisonBase, CultureInfo? culture) DateTimeHumanizeAlgorithms.PrecisionHumanize(input, comparisonBase, precision, culture); }两者差异集中在两点默认策略本主题用一系列固定阈值直接截断到最合适的单位简单直观、输出稳定是Configurator的默认选择精度策略接受一个precision默认 0.75参数在单位进位时做近似舍入如毫秒数 999 * precision才进位到秒适合需要微调边界行为的场景。测试辅助类 DateHumanize.cs 会按precision是否传入在这两个策略之间切换正是两者在测试体系中可互换的证明。在.NET 6目标框架下算法类还为DateOnly、TimeOnly提供了对应重载见 DateTimeHumanizeAlgorithms.cs行为与DateTime版本保持一致。实战使用与预期输出速查引入命名空间using Humanizer;后即可直接调用using Humanizer; var now DateTime.UtcNow; now.AddSeconds(-10).Humanize(); // 10 seconds ago now.AddMinutes(45).Humanize(); // 45 minutes from now now.AddHours(-23).Humanize(); // 23 hours ago now.AddDays(-1).Humanize(); // yesterday now.AddDays(1).Humanize(); // tomorrow now.AddDays(-13).Humanize(); // one week ago now.AddDays(-32).Humanize(); // one month ago now.AddDays(-400).Humanize(); // one year ago // 可空日期与显式文化 DateTime? never null; never.Humanize(); // never now.AddMonths(-10).Humanize(culture: new System.Globalization.CultureInfo(ru-RU));以上英文输出均可在 DateHumanizeDefaultStrategyTests.cs 的 Theory 数据中找到对应断言例如SecondsAgo60 秒 → a minute agoL4-L10HoursAgo24 小时 → yesterdayL42-L48DaysAgo7/13 天 → one week ago32 天 → one month agoL70-L79MonthsAgo12 个月 → one year agoL102-L108Now0 差值 → nowL130-L132。总结DefaultDateTimeHumanizeStrategy是 Humanizer 日期人性化的标准答案它实现IDateTimeHumanizeStrategy接口把全部计算委托给DateTimeHumanizeAlgorithms.DefaultHumanize通过一套由毫秒到年的分级阈值把TimeSpan距离映射为最合适的TimeUnit再借助文化相关的IFormatter输出本地化文案。理解它等于理解了DateTime.Humanize()的全部默认行为——包括 yesterday/tomorrow 的日历日判定、28~30 天的月份边界特判、一周内的周单位折算以及通过Configurator.DateTimeHumanizeStrategy替换为自定义或PrecisionDateTimeHumanizeStrategy的扩展路径。若需进一步研究接口契约可参考 IDateTimeHumanizeStrategy 文档或直接阅读 DateTimeHumanizeAlgorithms.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 中 DefaultDateTimeOffsetHumanizeStrategy 源码解析DateTimeOffset 相对时间人性化默认策略Humanizer 中 DefaultDateTimeOffsetHumanizeStrategy 源码解析DateTimeOffset 相对时间人性化默认策开发工具Humanizer 中 DefaultTimeOnlyHumanizeStrategy 源码解读TimeOnly 相对时间人性化的默认策略实现Humanizer 中 DefaultTimeOnlyHumanizeStrategy 源码解读TimeOnly 相对时间人性化的默认策略实现 本文围绕开发工具Humanizer 的 DefaultTimeOnlyHumanizeStrategy 详解TimeOnly 相对时间人文化的默认策略与源码剖析Humanizer 的 DefaultTimeOnlyHumanizeStrategy 详解TimeOnly 相对时间人文化的默认策略与源码剖析 导读 本文围开发工具上一篇NiGui未来路线图即将到来的macOS支持与新特性预览下一篇Awesome MCP Servers 项目教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

SQL Assessment API 服务要求(Service Requirement):为探针声明 SQL Server 服务依赖的完整指南
SQL Assessment API 服务要求(Service Requirement):为探针声明 SQL Server 服务依赖的完整指南

示例工程数据库教程后端 【免费下载链接】sql-server-samples Azure Data SQL Samples - Official Microsoft GitHub Repository containing code samples for SQL Server, Azure SQL, Azure Synapse, and Azure SQL Edge 项目地址: https://gitcode.com/gh_mirrors… · 2026/9/25 2:38:48

Hunk 0.14 发布详解:鼠标拖拽选择复制、折叠上下文内联展开与 Catppuccin 主题
Hunk 0.14 发布详解:鼠标拖拽选择复制、折叠上下文内联展开与 Catppuccin 主题

开发工具代码评审CLIAI 应用 【免费下载链接】hunk Review-first terminal diff viewer for agentic coders 项目地址: https://gitcode.com/gh_mirrors/hu/hunk 点击查看 免费下载 Hunk 0.14 是面向 agentic 编码者的 review-first 终端 diff 查看器在 2026 年 5 … · 2026/9/25 2:38:48

React 360 CLI 使用与生成器机制完全指南:用 `react-360 init` 一键创建 360° 项目
React 360 CLI 使用与生成器机制完全指南:用 `react-360 init` 一键创建 360° 项目

前端3D渲染 【免费下载链接】react-360 Create amazing 360 and VR content using React 项目地址: https://gitcode.com/gh_mirrors/re/react-360 点击查看 免费下载 本指南围绕 React 360 官方脚手架工具 react-360-cli 展开,讲解其安装方式、init 命… · 2026/9/25 2:38:48

react-native-skia 图像偏移过滤器 Offset 完全指南:属性、示例与底层实现
react-native-skia 图像偏移过滤器 Offset 完全指南:属性、示例与底层实现

图形学移动开发跨平台UI组件 【免费下载链接】react-native-skia High-performance React Native Graphics using Skia 项目地址: https://gitcode.com/gh_mirrors/re/react-native-skia 点击查看 免费下载 本文围绕 react-native-skia 提供的 Offset 图像过滤器展… · 2026/9/25 3:05:43

新春送福进一线:一场基层工会活动的策划与复盘
新春送福进一线:一场基层工会活动的策划与复盘

腊月下旬的北京,天亮得晚。活动室门口有人摸黑支桌子,红纸一卷一卷堆在墙角,砚台里的墨还没化开,凑近能闻到那股子墨香。常营地区总工会今年的"新春送福进一线"活动,就这么从一张桌子开始铺开了。说实话&… · 2026/9/25 3:05:43

easy-vibe 前端进阶教程:Figma 与 MasterGo 实战入门,从零创建网页原型
easy-vibe 前端进阶教程:Figma 与 MasterGo 实战入门,从零创建网页原型

教程文档 【免费下载链接】easy-vibe 从 0 到 1 学会 vibe coding,项目制学习 项目地址: https://gitcode.com/datawhalechina/easy-vibe 点击查看 免费下载 本文基于 easy-vibe 教程 Stage 2(初级-中级开发)前端方向的《Figma 与… · 2026/9/25 3:05:37

F´ 中的规则与场景驱动测试:基于 STest 的组件单元测试框架详解
F´ 中的规则与场景驱动测试:基于 STest 的组件单元测试框架详解

嵌入式系统编程 【免费下载链接】fprime F - A flight software and embedded systems framework 项目地址: https://gitcode.com/gh_mirrors/fpri/fprime 点击查看 免费下载 导读 STest 是 F(F Prime)飞行软件与嵌入式系统框架中内置的一个… · 2026/9/25 3:05:37

AI芯片架构选型指南:从GPU到TPU的实战对比
AI芯片架构选型指南:从GPU到TPU的实战对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:05:37

Win10 LTSC 2019老电脑优化指南:稳定、轻量、十年支持
Win10 LTSC 2019老电脑优化指南:稳定、轻量、十年支持

1. 为什么老电脑需要LTSC?不是“精简版”,而是“去冗余的官方原生系统”你手边那台奔腾G3258配4GB内存、机械硬盘还在吱呀作响的办公机,或者那台被塞进收银台底下、连USB3.0都没有的POS终端——它们真就该被淘汰吗?我去年帮本地一… · 2026/9/25 3:05:37

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码