news 2026/9/28 3:11:31

Humanizer OnDate.September 详解:用 Fluent API 优雅构造九月的每一天

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Humanizer OnDate.September 详解:用 Fluent API 优雅构造九月的每一天
  • 开发工具

【免费下载链接】Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

项目地址:https://gitcode.com/gh_mirrors/hu/Humanizer
点击查看免费下载

OnDate.September是 Humanizer FluentDate 体系中的一个静态访问器类,用于以"自然语言"风格直接获取当前年份九月中任意一天的System.DateOnly值,例如OnDate.September.The1st表示"今年的 9 月 1 日"。通过本文,你将掌握该类的全部 30 个静态属性与动态方法The(int dayNumber)的用法、其背后的 T4 模板生成原理,以及基于源码与测试用例的最佳实践与边界约束。

类定位:FluentDate 中的 DateOnly 访问器

OnDate.September定义于 Humanizer 的 FluentDate 目录 之下,命名空间为Humanizer,其 API 参考文档位于 Humanizer.OnDate.September.md。该类的完整声明为:

public class OnDate.September
  • 继承关系:System.Object→September,是一个普通静态成员类(本身非静态类,但所有成员均为静态)。
  • 返回类型:所有成员统一返回System.DateOnly,即 .NET 6 引入的"仅日期"结构体,不含时间分量。
  • 平台前提:对应实现被#if NET6_0_OR_GREATER条件编译保护(见 OnDate.Days.cs),因此该类仅在 .NET 6 及更高目标框架下可用。

从源码结构看,OnDate是面向DateOnly的整套 12 个月份访问器容器,同目录下还存在返回DateTime的On系列(On.Days.cs)以及面向相对时间的In/InDate系列,共同构成 Humanizer 的 FluentDate 日期表达式 DSL。

完整属性清单:The1st 到 The30th

与原 API 文档一致,OnDate.September提供 30 个静态只读属性,分别对应九月(30 天月份)的每一天。九月没有The31st,这是与 31 天月份类(如OnDate.January包含The31st,见 Humanizer.OnDate.January.md)的显著差异。

每个属性的声明形式均为:

public static System.DateOnly The10th { get; }

完整成员清单如下:

属性含义属性含义
The1st今年 9 月 1 日The16th今年 9 月 16 日
The2nd今年 9 月 2 日The17th今年 9 月 17 日
The3rd今年 9 月 3 日The18th今年 9 月 18 日
The4th今年 9 月 4 日The19th今年 9 月 19 日
The5th今年 9 月 5 日The20th今年 9 月 20 日
The6th今年 9 月 6 日The21st今年 9 月 21 日
The7th今年 9 月 7 日The22nd今年 9 月 22 日
The8th今年 9 月 8 日The23rd今年 9 月 23 日
The9th今年 9 月 9 日The24th今年 9 月 24 日
The10th今年 9 月 10 日The25th今年 9 月 25 日
The11th今年 9 月 11 日The26th今年 9 月 26 日
The12th今年 9 月 12 日The27th今年 9 月 27 日
The13th今年 9 月 13 日The28th今年 9 月 28 日
The14th今年 9 月 14 日The29th今年 9 月 29 日
The15th今年 9 月 15 日The30th今年 9 月 30 日

所有属性均为基于当前年份的计算属性:无论何时访问,返回的日期年份始终取DateTime.Now.Year,月份固定为 9,日期为属性名对应的序号。

动态方法:The(int dayNumber)

除了 30 个固定属性,OnDate.September还提供一个参数化入口,用于以变量方式指定九月中的任意一天:

public static System.DateOnly The(int dayNumber);
  • 参数:dayNumber(System.Int32),表示九月的第 N 天。
  • 返回值:System.DateOnly,即当前年份九月的第dayNumber天。

典型用法是配合循环或动态业务值构造日期,例如"距开学第 N 天"这类场景:

for (int day = 1; day <= 30; day++) { DateOnly date = OnDate.September.The(day); Console.WriteLine(date); // 输出今年 9 月 1 日 … 今年 9 月 30 日 }

从源码实现看,The(int dayNumber)直接执行new(DateTime.Now.Year, 9, dayNumber)。由于System.DateOnly构造函数会校验日期合法性,当dayNumber不在 1–30 的合法区间内时(例如 0、31 或负数),会抛出ArgumentOutOfRangeException,这一点在实际调用时需要自行保证参数范围。

实战示例:在项目中直接使用

以下代码可在 .NET 6+ 项目中直接运行(需引用 Humanizer 程序集并using Humanizer;):

using Humanizer; // 固定属性:开学纪念日(今年 9 月 1 日) DateOnly schoolOpening = OnDate.September.The1st; // 属性与 DateTime 互转 DateTime asDateTime = OnDate.September.The10th.ToDateTime(TimeOnly.MinValue); // 动态方法:报到日由变量决定 int checkInDay = 15; DateOnly checkIn = OnDate.September.The(checkInDay); // 与字符串化、序数化能力组合,输出如 "September 15" string label = checkIn.ToString("MMMM d"); Console.WriteLine($"开学日:{schoolOpening}"); Console.WriteLine($"报到日:{label}({checkIn})");

结合 Humanizer 的其他扩展,你可以进一步把该日期输出为自然语言,例如使用 DateToOrdinalWordsExtensions 或 DateHumanizeExtensions 生成"9 月 15 日"或"3 天前"等人类可读文案,使 FluentDate 的取值能力与 Humanizer 的格式化能力形成完整闭环。

源码实现与 T4 生成机制

OnDate.September的实现位于 OnDate.Days.cs,其核心逻辑极其精简——每个成员都只是一行表达式:

public class September { public static DateOnly The(int dayNumber) => new(DateTime.Now.Year, 9, dayNumber); public static DateOnly The1st => new(DateTime.Now.Year, 9, 1); // ... The30th 同理 }

值得注意的是,这 30 个属性并非手写,而是由 T4 文本模板 OnDate.Days.tt 自动生成的,模板机制可以总结为以下几点:

  • 闰年锚点:模板以leapYear = 2012为基准遍历 12 个月,确保 2 月 29 日这类"仅闰年存在"的日期也能被覆盖到。
  • 月份名推导:通过new DateTime(leapYear, month, 1).ToString("MMMM")获得本地化月份名(如September),并据此生成对应类名。
  • 天数推导:用DateTime.DaysInMonth(leapYear, month)计算当月天数,因此 9 月只会生成The1st–The30th,不会有 31 号。
  • 序数词生成:调用 Humanizer 的day.Ordinalize()把数字转成1st、2nd、3rd、21st、22nd、23rd、30th等属性名后缀,这正是属性命名中 11/12/13 与 21/22/23 后缀差异的来源。
  • 条件编译:模板整体输出被#if NET6_0_OR_GREATER包裹,与DateOnly的可用性保持一致。

理解了这套生成机制,就可以从源码层面解释该 API 文档中的每一个成员:它们不是手写常量,而是由"固定年份 + 月份 + 序号"模板批量推导的、随DateTime.Now.Year动态变化的计算属性。

测试验证与使用注意事项

Humanizer 仓库在 OnDateTests.cs 中为该系列提供了验证用例,例如:

[Fact] public void OnJanuaryThe23rd() => Assert.Equal(new(DateTime.Now.Year, 1, 23), OnDate.January.The23rd); [Fact] public void OnFebruaryThe() => Assert.Equal(new(DateTime.Now.Year, 2, 11), OnDate.February.The(11));

同样的模式适用于OnDate.September(将月份换为 9)。基于源码与测试,使用时有以下几点值得注意:

  1. 年份动态性:所有成员返回"当前年份"的九月日期,跨年调用会产生不同的DateOnly;若需要指定年份,应改用new DateOnly(year, 9, day)自行构造。
  2. 合法范围:固定属性天然限定在 1–30;The(int dayNumber)接受任意int,但非 1–30 的值会触发DateOnly构造时的参数校验异常,业务代码应先做边界判断。
  3. 框架版本:类仅在NET6_0_OR_GREATER下编译,面向 .NET Framework 或 .NET 5 的项目无法使用该 API,可退回On.September(返回DateTime)系列。
  4. 静态调用:所有成员均为静态,无需实例化OnDate或September,直接以OnDate.September.The15th形式调用即可。

相关资源

  • API 参考:Humanizer.OnDate.September.md
  • 源码实现:OnDate.Days.cs
  • 生成模板:OnDate.Days.tt
  • 测试用例:OnDateTests.cs
  • 同类 API:Humanizer.OnDate.January.md(含 31 天对照)
  • 开发工具

【免费下载链接】Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

项目地址:https://gitcode.com/gh_mirrors/hu/Humanizer
点击查看免费下载
上一篇:ViGEmBus虚拟手柄驱动终极指南:5分钟让任何手柄变Xbox控制器
下一篇:天穹飞控GPS定点悬停调参指南:从打杆匀加速到刹车匀减速的实现

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 3:10:36

信息聚合器:WorldMonitor、Folo、Crucix、AI Daily Digest、Open Scouts

继热点信息聚合器&#xff1a;TrendRadar、BettaFish、NewsNow、ClawFeed之后&#xff0c;本文继续搜集汇总介绍几个开源信息聚合项目。 WorldMonitor 官网&#xff0c;开源&#xff08;GitHub&#xff0c;56.7K Star&#xff0c;9.1K Fork&#xff09;的实时情报/监测仪表盘…

作者头像 李华
网站建设 2026/9/28 3:07:56

随机森林预测锂电池剩余寿命:从数据处理到模型实战

简介&#xff1a;基于Python随机森林的锂离子电池剩余寿命预测项目资料包含丰富&#xff0c;面向需要完成毕设、课程设计或工程实训的初学者和进阶学习者。资料围绕电池寿命预测任务&#xff0c;从现有方法调研到数据处理与模型构建均有涉及&#xff0c;重点演示了利用pandas、…

作者头像 李华
网站建设 2026/9/28 3:04:35

TCP十大核心机制详解

上篇文章&#xff0c;我为大家介绍和演示了关于 UDP 和 TCP 两个协议的网络编程&#xff0c;两个协议的网络编程还是有一定的区别&#xff0c;我个人感觉 TCP 的网络编程会比 UDP 的复杂不少&#xff0c;也更需要我们去理解&#xff0c;并且熟练地掌握。这篇文章&#xff0c;我…

作者头像 李华