开发工具【免费下载链接】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点击查看免费下载导读IDateToOrdinalWordConverter是 Humanizer 中负责把日期DateTime转换为本地化序数词日期Ordinal Words的扩展点接口是ToOrdinalWords()扩展方法全部能力的底层契约。本文以该接口为骨架结合仓库中默认实现、模式化转换器、注册表与测试用例讲清它的两个Convert方法签名、各文化下的真实输出规则、语法格GrammaticalCase的作用边界以及如何在Configurator上自定义自己的转换器。接口概览它解决什么问题在 Humanizer 中把DateTime变成1st of January, 2023这类人类可读日期文本的能力被抽象为IDateToOrdinalWordConverter接口。官方文档对该接口的定义只有一句话The interface used to localise the ToOrdinalWords method用于本地化ToOrdinalWords方法的接口但它的背后牵动着一整套按文化culture注册、按日历解析、按月名属格替换的实现体系。接口完整签名如下摘自 src/Humanizer/Localisation/DateToOrdinalWords/IDateToOrdinalWordConverter.csnamespace Humanizer; public interface IDateToOrdinalWordConverter { string Convert(DateTime date); string Convert(DateTime date, GrammaticalCase grammaticalCase); }接口包含两个方法方法说明参数返回值Convert(DateTime date)将日期转换为序数词日期文本date待格式化的DateTime本地化序数日期字符串Convert(DateTime date, GrammaticalCase grammaticalCase)使用指定语法格转换日期dategrammaticalCase目标语法格如 Nominative、Genitive 等本地化序数日期字符串第二个重载的存在是为了支持俄语、波兰语等有格变case system的语言同一个日期在不同的语法语境下主格、属格……需要输出不同的词形。对英语这类没有格变的语言该参数不产生效果。语法格的完整枚举定义见 Humanizer.GrammaticalCase。调用链从扩展方法到接口接口并不是直接暴露给使用者的 API日常编码中你调用的是DateToOrdinalWordsExtensions提供的扩展方法src/Humanizer/DateToOrdinalWordsExtensions.cspublic static string ToOrdinalWords(this DateTime input) Configurator.DateToOrdinalWordsConverter.Convert(input); public static string ToOrdinalWords(this DateTime input, GrammaticalCase grammaticalCase) Configurator.DateToOrdinalWordsConverter.Convert(input, grammaticalCase);即ToOrdinalWords()→Configurator.DateToOrdinalWordsConverter→ 按当前文化解析出的具体IDateToOrdinalWordConverter实现 →Convert。Configurator内部持有注册表并按文化解析src/Humanizer/Configuration/Configurator.cspublic static LocaliserRegistryIDateToOrdinalWordConverter DateToOrdinalWordsConverters { get; } new DateToOrdinalWordsConverterRegistry(); internal static IDateToOrdinalWordConverter DateToOrdinalWordsConverter DateToOrdinalWordsConverters.ResolveForCulture(null);ResolveForCulture(null)表示用当前线程的CultureInfo.CurrentCulture决定选用哪个文化的实现这正体现了 Humanizer 跟着当前文化走的本地化设计。默认实现DefaultDateToOrdinalWordConverter所有文化在未注册专门实现时的兜底转换器是DefaultDateToOrdinalWordConvertersrc/Humanizer/Localisation/DateToOrdinalWords/DefaultDateToOrdinalWordConverter.cs其内部逻辑清晰地区分了英语与非英语两条路径英语路径真正的序数词return date.Day.Ordinalize() date.ToString( MMMM yyyy);即把日部分做序数化1→1st、2→2nd、22→22nd再接上 MMMM yyyy格式的月与年。因此new DateTime(2023, 1, 1).ToOrdinalWords()→1st of January, 2023new DateTime(2020, 12, 22).ToOrdinalWords()→22nd of December, 2020以上示例同时见于扩展方法的 XML 注释与扩展方法签名所在的源码文件中。非英语路径短日期 方向标记清洗var culture CultureInfo.CurrentCulture; if (culture.TwoLetterISOLanguageName ! en) { return SanitizeNonEnglishDate(date.ToString(d, culture)); } static string SanitizeNonEnglishDate(string value) value.Replace(LeftToRightMark.ToString(), string.Empty) .Replace(RightToLeftMark.ToString(), string.Empty) .Replace(ArabicLetterMark.ToString(), string.Empty);要点有二直接使用当前文化的短日期模式d——因为非英语文化本身已经知道如何排列日期的年月日顺序Humanizer 不再强行改写成序数词短语剥离嵌入的方向控制符希伯来语、阿拉伯语等日历在短日期输出中可能嵌入左到右标记U200E、右到左标记U200F和阿拉伯字母标记U061C。这些标记一旦混入更大的序数短语文本会造成阅读混乱因此默认实现统一清除。语法格重载英语下被忽略第二个Convert(DateTime, GrammaticalCase)在默认实现中直接转发给单参版本public virtual string Convert(DateTime date, GrammaticalCase grammaticalCase) Convert(date);这与扩展方法文档中的说明一致grammaticalCase参数主要服务于有格变的语言对英语无效。需要注意默认实现不感知语法格——真正按语法格输出不同词形的是各个语言专门注册的模式化转换器。模式化实现OrdinalDatePattern 与 PatternDateToOrdinalWordsConverter大量语言并不使用兜底逻辑而是通过 Source Generator 依据 yml 语言资源生成专门的转换器注册。这些转换器大多继承DefaultDateToOrdinalWordConverter但覆写Convert以使用预构建的模式对象src/Humanizer/Localisation/DateToOrdinalWords/PatternDateToOrdinalWordsConverter.csclass PatternDateToOrdinalWordsConverter(OrdinalDatePattern pattern) : DefaultDateToOrdinalWordConverter { public override string Convert(DateTime date) pattern.Format(date); }日分量渲染模式OrdinalDateDayModeOrdinalDatePattern支持 5 种日分量渲染方式src/Humanizer/Localisation/DateToOrdinalWords/OrdinalDatePattern.cs模式行为Numeric日分量按文化感知的数字输出Ordinal日分量输出为序数词OrdinalWhenDayIsOne除非是每月 1 日输出序数否则输出数字MasculineOrdinalWhenDayIsOne每月 1 日输出阳性序数形式服务于有语法性别的语言DotSuffix数字后追加圆点后缀如某些中欧语言的25.写法日历模式OrdinalDateCalendarMode模式对象还控制日历解析方式src/Humanizer/Localisation/DateToOrdinalWords/OrdinalDateCalendarMode.csGregorian无论文化的默认日历是什么强制使用本地化格里高利历GregorianCalendar(GregorianCalendarTypes.Localized)失败时回退到OptionalCalendars中的格里高利历Native保留文化默认日历如泰国佛历、希伯来历、波斯历让DateTime.ToString()输出本地化的年份。月名属格替换OrdinalDatePattern内还实现了对模板中首个未转义MMMM的替换逻辑当日说明符d/dd注意不是ddd/dddd星期说明符紧邻月名说明符时会启用属格genitive月名数组monthsGenitive以支持俄语、波兰语等斯拉夫语系在25 мая这类搭配中月名发生格变的现象同时支持希吉来历Hijri / UmAlQura的专用月名数组。所有输出在返回前同样经过方向控制符清洗。注册与自定义LocaliserRegistry 与 Configurator默认注册表在 src/Humanizer/Configuration/DateToOrdinalWordsConverterRegistry.cs 中定义class DateToOrdinalWordsConverterRegistry : LocaliserRegistryIDateToOrdinalWordConverter { public DateToOrdinalWordsConverterRegistry() : base(_ new DefaultDateToOrdinalWordConverter()) DateToOrdinalWordsConverterRegistryRegistrations.Register(this); }基类构造参数_ new DefaultDateToOrdinalWordConverter()是兜底工厂任何没有显式注册的文化都会解析到默认实现DateToOrdinalWordsConverterRegistryRegistrations.Register(this)是由 Source Generator 生成的静态注册方法为各语言写入其专属转换器生成输入模型见 src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/OrdinalDateProfileCatalogInput.cs。若要自定义某个文化的日期序数词输出可向Configurator暴露的注册表注册自定义实现// 将自定义转换器应用到某个特定文化 Configurator.DateToOrdinalWordsConverters .RegisterMyCulture(() new MyCustomDateToOrdinalWordConverter());自定义转换器只需实现IDateToOrdinalWordConverter的两个Convert方法对于仅需微调格式的场景继承DefaultDateToOrdinalWordConverter并覆写单参Convert即可GrammaticalCase重载默认仍会转发到你覆写的方法上。配套能力DateOnly 支持除DateTime外Humanizer 还为 .NET 6 提供了DateOnly的序数词转换走的是平行的IDateOnlyToOrdinalWordConverter接口与DateOnlyToOrdinalWordsConverters注册表见 src/Humanizer/DateToOrdinalWordsExtensions.cs 中#if NET6_0_OR_GREATER分支并通过PatternDateOnlyToOrdinalWordsConverter、DefaultDateOnlyToOrdinalWordConverter等实现类复用同一套模式逻辑src/Humanizer/Localisation/DateToOrdinalWords/。OrdinalDatePattern为此专门提供了Format(DateOnly)重载。测试验证各语言输出有据可查仓库测试目录中有大量针对ToOrdinalWords的语言级测试可当作行为规格书使用。例如斯瓦希里语测试tests/Humanizer.Tests/Localisation/sw/SwahiliDateToOrdinalWordsTests.cs[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()); } }可以看到在sw文化下输出既不是英语的25th of January风格也不是数字序列而是25 Januari 2022——这正是模式化转换器按语言资源格式化后的结果。类似的语言级测试还覆盖了 Hausa、Igbo、Punjabi、Hindi、Nepali、Somali、Urdu 等分布在 tests/Humanizer.Tests/Localisation/ 对应子目录。公共 API 面含IDateToOrdinalWordConverter的公开签名则由 API 审批测试锁定见 tests/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.Approve_Public_Api.DotNet8_0.verified.txt。小结IDateToOrdinalWordConverter虽只暴露两个Convert方法却是 Humanizer 日期本地化体系的最小契约它连接了面向用户的ToOrdinalWords()扩展、按文化解析的LocaliserRegistry、默认兜底的DefaultDateToOrdinalWordConverter以及由 Source Generator 驱动、支持语法格与属格月名的OrdinalDatePattern模式体系。理解这个接口就等于拿到了定制任意语言日期序数词输出的钥匙改一个实现类、注册一次文化ToOrdinalWords()的输出便随之改变。赞分享开发工具【免费下载链接】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 的 IDateToOrdinalWordConverter日期转序数词文本的本地化转换接口解析Humanizer 的 IDateToOrdinalWordConverter日期转序数词文本的本地化转换接口解析 IDateToOrdinalWordCon开发工具Humanizer 的 IDateToOrdinalWordConverter 接口定制本地化日期序数词转换的完整指南Humanizer 的 IDateToOrdinalWordConverter 接口定制本地化日期序数词转换的完整指南 导读 IDateToOrdinalWo开发工具Humanizer 本地化日期序数词转换IDateOnlyToOrdinalWordConverter 接口全解Humanizer 本地化日期序数词转换IDateOnlyToOrdinalWordConverter 接口全解 在 Humanizer 中把日期如 20开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考