Humanizer 本地化接口 `IDateOnlyToOrdinalWordConverter` 深度解析:DateOnly 序数词日期的转换机制与自定义实现
发布时间:2026/9/27 7:00:55来源:尧图网络
开发工具【免费下载链接】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点击查看免费下载IDateOnlyToOrdinalWordConverter是 Humanizer 中负责把 .NET 6 的System.DateOnly值转换为本地化序数词日期Ordinal Words文本的核心抽象接口支撑着DateOnly.ToOrdinalWords()扩展方法的全部行为。本文以该接口的官方 API 参考文档为主体结合 Humanizer 仓库中的接口定义、默认实现、注册表机制与测试用例系统讲解其方法签名、底层原理、文化差异处理以及如何自定义实现帮助你在自己的 .NET 项目中精确控制日期序数词的输出格式。接口概述它解决什么问题在文档 Humanizer.Localisation.DateToOrdinalWords.IDateOnlyToOrdinalWordConverter 中该接口被定义为The interface used to localise the ToOrdinalWords method.也就是说它专门服务于ToOrdinalWords的本地化当你在英语环境下调用new DateOnly(2023, 1, 1).ToOrdinalWords()得到1st of January, 2023时真正干活的就是当前文化所解析出的IDateOnlyToOrdinalWordConverter实现见 DateToOrdinalWordsExtensions.cs 中Configurator.DateOnlyToOrdinalWordsConverter.Convert(input)的调用链。接口的完整签名在仓库源码 IDateOnlyToOrdinalWordConverter.cs 中定义并且整个类型被#if NET6_0_OR_GREATER条件编译包裹——因为DateOnly类型本身从 .NET 6 才开始引入。也就是说该接口只在 .NET 6 及以上目标框架中可用这与扩展方法 DateToOrdinalWordsExtensions.cs 中的同款条件编译保持严格一致。#if NET6_0_OR_GREATER namespace Humanizer; /// summary /// Converts dates into the localized text used by cToOrdinalWords/c. /// /summary public interface IDateOnlyToOrdinalWordConverter { string Convert(DateOnly date); string Convert(DateOnly date, GrammaticalCase grammaticalCase); } #endif值得注意的是Humanizer 同时还存在一个面向DateTime的姊妹接口IDateToOrdinalWordConverter见 IDateToOrdinalWordConverter.cs两者的方法形状完全对称区别仅在于输入参数类型。IDateOnlyToOrdinalWordConverter是为现代 .NET 的纯日期类型单独设计的专用契约。Convert(DateOnly)基础转换方法签名与语义string Convert(System.DateOnly date);文档对该方法的描述是 Converts the date to Ordinal Words即把给定日期转换为当前文化下的序数词日期字符串。参数date为System.DateOnly返回值是System.String。默认实现的行为差异Humanizer 提供的默认实现DefaultDateOnlyToOrdinalWordConverter见 DefaultDateOnlyToOrdinalWordConverter.cs非常巧妙地处理了英语与非英语两类文化的差异英语文化TwoLetterISOLanguageName en将日期中的日部分先做序数词化再拼接月份与年份例如date.Day.Ordinalize() date.ToString( MMMM yyyy)产出1st of January, 2023、22nd of December, 2020这样的结果非英语文化直接复用当前文化自己的短日期模式date.ToString(d, culture)因为很多语言本身已经内置了正确的日期排序与本地化格式Humanizer 不需要额外干预。方向性控制符的清理非英语路径还有一个容易被忽略的细节某些日历尤其是 RTL 语言环境在短日期输出中会嵌入 Unicode 方向性控制符例如U200ELeft-To-Right Mark、U200FRight-To-Left Mark和U061CArabic Letter Mark。默认实现中的SanitizeNonEnglishDate方法会把这些字符逐一剥离避免序数词日期被嵌入更大的短语时出现排版混乱。static string SanitizeNonEnglishDate(string value) value.Replace(LeftToRightMark.ToString(), string.Empty) .Replace(RightToLeftMark.ToString(), string.Empty) .Replace(ArabicLetterMark.ToString(), string.Empty);Convert(DateOnly, GrammaticalCase)带语法格的重载签名与语义string Convert(System.DateOnly date, Humanizer.GrammaticalCase grammaticalCase);文档描述为 Converts the date to Ordinal Words using the provided grammatical case。除date参数外本重载多出一个grammaticalCase参数类型为Humanizer.GrammaticalCaseAPI 参考文档中通过相对链接指向 Humanizer.GrammaticalCase.md。GrammaticalCase枚举的全貌GrammaticalCase.cs 中定义的枚举包含约 30 个成员覆盖了世界主要语言的格体系例如印欧语系常见格Nominative主格、Genitive属格、Dative与格、Accusative宾格、Instrumental工具格、Prepositional前置格等乌拉尔语系/亚非语系等特色格Partitive部分格、Vocative呼格、Illative入格、Adessive接格、Essive样格等南亚语言特有格Sociative、Benefactive等。该参数在什么情况下真正生效关键语义在扩展方法的 XML 文档中有明确说明见 DateToOrdinalWordsExtensions.csThe grammatical case parameter is primarily used by languages that have case systems. For languages without grammatical cases (like English), this parameter has no effect.也就是说grammaticalCase主要服务于俄语、波兰语、乌克兰语这类名词有格变化的语言在构建日期短语时需要根据句法位置选择正确的格形式而对于英语等没有格系统的语言传不传该参数结果完全一致。这一点在默认实现中体现得更为直接——DefaultDateOnlyToOrdinalWordConverter的双参数重载只是简单转发给单参数版本并明确注释grammaticalCase参数被忽略见 DefaultDateOnlyToOrdinalWordConverter.cspublic virtual string Convert(DateOnly date, GrammaticalCase grammaticalCase) Convert(date);注册与解析机制接口如何与文化和配置挂钩配置入口ConfiguratorHumanizer 把所有本地化组件都聚合在 Configurator.cs 中。其中与本文主题相关的有两个成员公开注册表public static LocaliserRegistryIDateOnlyToOrdinalWordConverter DateOnlyToOrdinalWordsConvertersConfigurator.cs内部解析快捷入口internal static IDateOnlyToOrdinalWordConverter DateOnlyToOrdinalWordsConverter它通过DateOnlyToOrdinalWordsConverters.ResolveForCulture(null)按当前文化解析出具体实现Configurator.cs。扩展方法ToOrdinalWords最终调用的正是这个内部属性因此改变CultureInfo.CurrentCulture或注册不同的转换器实现都会立即影响DateOnly.ToOrdinalWords()的输出。注册表默认行为DateOnlyToOrdinalWordsConverterRegistry.cs 中展示了注册表的构造逻辑class DateOnlyToOrdinalWordsConverterRegistry : LocaliserRegistryIDateOnlyToOrdinalWordConverter { public DateOnlyToOrdinalWordsConverterRegistry() : base(_ new DefaultDateOnlyToOrdinalWordConverter()) DateOnlyToOrdinalWordsConverterRegistryRegistrations.Register(this); }这里有两层含义其一基础工厂函数以DefaultDateOnlyToOrdinalWordConverter作为兜底其二DateOnlyToOrdinalWordsConverterRegistryRegistrations.Register(this)是源码生成器生成的注册代码会把各语言配置文件中声明的 profile 注册进去。源码生成器如何生成注册在 GenerationHelpers.cs 中可以看到生成器对DateOnlyToOrdinalWordsConverterRegistry的两种分支处理static string? CreateDateOnlyToOrdinalWords(string profile) profile default ? new DefaultDateOnlyToOrdinalWordConverter() : DateOnlyToOrdinalWordsProfileCatalog.Resolve( Quote(profile) );即当某个语言的配置 profile 为default时直接使用默认转换器否则通过DateOnlyToOrdinalWordsProfileCatalog按 profile 名称解析解析结果通常是基于OrdinalDatePattern构建的PatternDateOnlyToOrdinalWordsConverter。底层实现OrdinalDatePattern的格式化原理当某个语言配置了专门的日期序数词 pattern 时Humanizer 使用PatternDateOnlyToOrdinalWordsConverter完成转换见 PatternDateOnlyToOrdinalWordsConverter.cs它继承自默认转换器并重写Convert把格式化委托给OrdinalDatePattern.Format(date)。模式模板与占位符OrdinalDatePattern.cs 是这套机制的核心。其设计要点包括模板字符串中可以包含{day}占位符格式化完成后再替换为实际渲染的日文本占位符被替换为dDAY这种真实d说明符 标记的组合目的是让 .NET 的DateTimeFormatInfo看到一个日 月的完整模式从而在斯拉夫语系等语言中正确触发属格genitive月份名格式化后数字日与标记一起被剥离再插入渲染好的日文本SubstituteMonth方法会扫描格式串中第一个未转义的MMMM将其替换为语言包中声明的月份名数组支持普通与属格两套数组并遵循DateTimeFormatInfo的引号转义规则属格月份名的触发条件是日说明符d/dd非ddd/dddd紧邻月份说明符例如dDAY MMMM或MMMM d模式IsDayAdjacentToMonth与FindAdjacentDayOfMonth负责这项判定OrdinalDatePattern.cs。五种日渲染模式OrdinalDateDayMode枚举OrdinalDatePattern.cs决定了日期中日部分的呈现方式FormatDay方法OrdinalDatePattern.cs据此分派模式行为Numeric以文化感知的数字形式渲染日Ordinal渲染为序数词如英语1stOrdinalWhenDayIsOne除每月 1 号渲染序数词外其余用数字MasculineOrdinalWhenDayIsOne每月 1 号使用阳性序数词服务于有语法性别的语言DotSuffix数字后附加句点后缀如捷克语等语言的惯例写法日历模式的控制OrdinalDateCalendarMode枚举OrdinalDateCalendarMode.cs控制格式化的日历解析策略Gregorian无论文化默认日历如何强制使用本地化格里高利历Native使用文化的默认日历如泰历佛历、希伯来历、波斯历。OrdinalDatePattern.GetPatternCulture方法OrdinalDatePattern.cs负责实现这一策略Native模式下直接返回克隆的当前文化使DateTime.ToString()输出原生年份Gregorian模式则尝试把DateTimeFormat.Calendar切换为GregorianCalendar若失败则遍历OptionalCalendars寻找可用的格里高利历。测试验证与实际输出Humanizer 仓库中有大量针对DateOnly序数词转换的测试可以作为行为规范直接参考。以 SwahiliDateToOrdinalWordsTests.cs 为例斯瓦希里文化下日期被渲染为25 Januari 2022这样不带序数词标记的格式且DateTime与DateOnly两个扩展方法行为保持一致[UseCulture(sw)] public class SwahiliDateToOrdinalWordsTests { [Theory] [InlineData(2022, 1, 25, 25 Januari 2022)] [InlineData(2015, 2, 3, 3 Februari 2015)] public void DateTimeToOrdinalWords_UsesSwahiliDatePattern(int year, int month, int day, string expected) { Assert.Equal(expected, new DateTime(year, month, day).ToOrdinalWords()); } #if NET6_0_OR_GREATER [Theory] [InlineData(2022, 1, 25, 25 Januari 2022)] [InlineData(2015, 2, 3, 3 Februari 2015)] public void DateOnlyToOrdinalWords_UsesSwahiliDatePattern(int year, int month, int day, string expected) { Assert.Equal(expected, new DateOnly(year, month, day).ToOrdinalWords()); } #endif }类似的测试还覆盖豪萨语、伊博语、索马里语等新近加入的语言见 HausaDateToOrdinalWordsTests.cs、IgboDateToOrdinalWordsTests.cs、SomaliDateToOrdinalWordsTests.cs它们共同验证了注册表解析 Pattern 格式化这条链路的正确性。如何自定义实现IDateOnlyToOrdinalWordConverter是公开接口你可以通过实现它来完全接管日期序数词的本地化输出典型场景包括为某个未覆盖的语言提供专属格式、对现有语言的输出做二次定制、或者在特殊日历下强制某种渲染风格。自定义实现的基本步骤如下实现接口实现Convert(DateOnly)与Convert(DateOnly, GrammaticalCase)两个方法。若不关心语法格双参数版本直接转发给单参数版本即可与默认实现的策略一致注册实现通过Configurator.DateOnlyToOrdinalWordsConverters注册表按文化注册你的实现。注册表基于LocaliserRegistryT会按当前文化解析合适的转换器保持与扩展方法的衔接注册完成后dateOnly.ToOrdinalWords()会自动路由到你的实现无需改动调用方代码。从源码结构可以推断Humanizer 对绝大多数语言的日期序数词支持都建立在默认实现 数据驱动的OrdinalDatePattern模板之上因此在实现自定义转换器之前优先检查目标语言是否已在src/Humanizer/Locales/目录的 YAML 语言包中声明了日期 pattern 模板通常是更省力且更符合项目生态的做法。小结IDateOnlyToOrdinalWordConverter是 Humanizer 本地化体系中专为 .NET 6DateOnly设计的核心契约它定义了日期 → 序数词日期文本的两个转换方法通过 Configurator.cs 与源码生成器驱动的注册表按文化解析具体实现背后由DefaultDateOnlyToOrdinalWordConverter的英语/非英语分流策略、OrdinalDatePattern的模板化格式化、属格月份名处理、日历模式选择与方向性控制符清理等一系列机制共同支撑。理解这个接口及其实现链路你就能在 .NET 项目中准确控制序数词日期的输出并在需要时以最小成本接入自定义本地化方案。赞分享开发工具【免费下载链接】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 本地化日期序数词转换IDateOnlyToOrdinalWordConverter 接口全解Humanizer 本地化日期序数词转换IDateOnlyToOrdinalWordConverter 接口全解 在 Humanizer 中把日期如 20开发工具MAA明日方舟助手一键跑完全部日常把 30 分钟重复劳动交给它MAA明日方舟助手一键跑完全部日常把 30 分钟重复劳动交给它 MAAMaaAssistantArknights是基于图像识别的《明日方舟》日常辅助工具开发工具Humanizer.IDateOnlyToOrdinalWordConverter 接口深度解析DateOnly 本地化序数日期转换Humanizer.IDateOnlyToOrdinalWordConverter 接口深度解析DateOnly 本地化序数日期转换 IDateOnlyToO开发工具上一篇在Obsidian中打造你的个人日程管理中心完整使用指南下一篇React Chrono富媒体集成图片、视频和YouTube嵌入完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网