ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Humanizer 的 InDate.One:用 Fluent API 计算“从现在起一天/一周/一月/一年“的 DateOnly 日期

2026/9/25 13:58:00 拓冰建站 浏览量
Humanizer 的 InDate.One:用 Fluent API 计算“从现在起一天/一周/一月/一年“的 DateOnly 日期 开发工具【免费下载链接】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点击查看免费下载导读InDate.One是 Humanizer 的 Fluent Date 体系中针对数字1的日期计算门面专门用来生成距离现在或给定基准日期1 天、1 周、1 个月、1 年的 [DateOnly] 值。本文以 v2.11.10 API 文档 Humanizer.InDate.One.md 为主线深入源码实现与测试用例说明该类型 4 个属性与 8 个方法的完整签名、UTC 语义、日历化加减的边界行为以及它与In.One返回DateTime之间的分工帮助你写出可读、可测试、无歧义的日期计算代码。类型概览InDate.One是什么InDate.One是嵌套在Humanizer.InDate内的一个public static class其完整声明为public static class InDate.One从继承关系看它最终派生自System.Object。它不是一个普通可实例化的日期对象而是一组静态成员容器——没有构造函数、没有实例状态所有成员均为static直接通过InDate.One.Xxx调用。它的所有属性与方法的返回值类型都是System.DateOnly.NET 6 引入的纯日期类型不含时间部分这也是它与In.One返回DateTime最本质的区别。在实际源码中One与Two到Ten这些数字类共同定义在 InDate.SomeTimeFrom.cs 中外层由InDate这个partial class承载同文件里还并列定义了Two、Three……Ten也就是说InDate.One只是InDate.一至十系列的第一个成员。该系列源码整体被#if NET6_0_OR_GREATER条件编译指令包裹即只有在 .NET 6 及以上目标框架上才会编译进程序集。与In.One的关系Humanizer 中另有一个平行的静态类In.One定义于 In.SomeTimeFrom.cs其成员签名与InDate.One一一对应但返回值是DateTime保留时分秒同样基于 UTC。二者的对应关系如下能力In.One返回DateTimeInDate.One返回DateOnly属性从现在起Second/Minute/Hour/Day/Week/Month/YearDay/Week/Month/Year方法从基准日同名XxxFrom(DateTime)系列XxxFrom(DateOnly)与XxxFrom(DateTime)双重载差异点有二其一In.One多出秒、分、时三个粒度Second/Minute/HourInDate.One只保留日、周、月、年四个日历粒度因为DateOnly本身就只表达日期其二InDate.One的XxxFrom方法同时提供DateOnly与DateTime两种参数重载方便两种日期形态互相衔接。属性从现在起算的四个只读值InDate.One暴露四个静态只读属性getter-only语义均为从现在起 1 个单位之后的那一天文档原文分别描述为 1 days from now、1 weeks from now、1 months from now、1 years from now属性签名文档语义底层实现Daypublic static DateOnly Day { get; }1 days from nowDateOnly.FromDateTime(DateTime.UtcNow.AddDays(1))Weekpublic static DateOnly Week { get; }1 weeks from nowDateOnly.FromDateTime(DateTime.UtcNow.AddDays(7))Monthpublic static DateOnly Month { get; }1 months from nowDateOnly.FromDateTime(DateTime.UtcNow.AddMonths(1))Yearpublic static DateOnly Year { get; }1 years from nowDateOnly.FromDateTime(DateTime.UtcNow.AddYears(1))需要特别强调的是时区语义这四个属性虽然返回DateOnly不含时间但内部基准时刻是DateTime.UtcNow而非DateTime.Now见 InDate.SomeTimeFrom.cs 等处的实现。这意味着1 天之后的判定以 UTC 日期边界为准。例如在 UTC8 的时区本地时间 23:30 对应的 UTC 日期可能已经是明天此时InDate.One.Day返回的日期可能与本地直觉相差一天。若你的业务日期以本地时区为边界应改用传入基准日期的XxxFrom形式。另外Week的实现是AddDays(7)而非独立的周单位运算与Day的AddDays(1)保持同一套固定天数逻辑而Month、Year则走AddMonths(1)、AddYears(1)的日历化运算规则差异详见后文。属性为何不适合确定性代码由于四个属性每次求值都读取UtcNow它们是运行时依赖当前时间的非确定性表达式。官方场景指南 fluent-dates-and-time-spans.mdx 明确将其列为 Pitfall无From后缀的属性会读取Now/UtcNow在需要可重复执行的代码单元测试、批处理、定时任务中应避免使用。替代方案是传入固定基准日期的XxxFrom方法。方法从指定基准日计算的八个重载InDate.One提供 8 个静态方法按单位分为 4 组每组都有DateOnly与DateTime两个重载。它们的文档语义均为 1 X from the provided date以给定日期为基准向后推进 1 个单位。DayFrompublic static DateOnly DayFrom(DateOnly date); // date.AddDays(1) public static DateOnly DayFrom(DateTime date); // DateOnly.FromDateTime(date.AddDays(1))DayFrom(DateOnly)直接调用date.AddDays(1)返回结果仍是DateOnlyDayFrom(DateTime)先对传入的DateTime执行AddDays(1)再用DateOnly.FromDateTime剥离时间部分。二者都不会触碰系统时钟因此适合测试与确定性业务逻辑。WeekFrompublic static DateOnly WeekFrom(DateOnly date); // date.AddDays(7) public static DateOnly WeekFrom(DateTime date); // DateOnly.FromDateTime(date.AddDays(7))一周在这里被定义为固定的 7 个自然日AddDays(7)与日历上下周一这种按星期对齐的语义无关。如果你需要下个星期一这类星期对齐逻辑那不属于InDate.One的职责范围。MonthFrompublic static DateOnly MonthFrom(DateOnly date); // date.AddMonths(1) public static DateOnly MonthFrom(DateTime date); // DateOnly.FromDateTime(date.AddMonths(1))MonthFrom走AddMonths(1)属于日历化运算它会按目标月份的月末进行规范化normalization。例如从 1 月 31 日起算 1 个月2 月没有 31 日结果会被规整到 2 月 28 日或闰年 2 月 29 日。这与固定 30 天的估算完全不同。YearFrompublic static DateOnly YearFrom(DateOnly date); // date.AddYears(1) public static DateOnly YearFrom(DateTime date); // DateOnly.FromDateTime(date.AddYears(1))YearFrom走AddYears(1)同样是日历化运算。最典型的边界是闰日从 2024-02-29 起算 1 年2025 年不是闰年结果会被规范化为 2025-02-28参见 InDate.SomeTimeFrom.cs 的实现。方法族完整对照表方法DateOnly重载实现DateTime重载实现运算类型DayFromdate.AddDays(1)DateOnly.FromDateTime(date.AddDays(1))固定天数WeekFromdate.AddDays(7)DateOnly.FromDateTime(date.AddDays(7))固定天数MonthFromdate.AddMonths(1)DateOnly.FromDateTime(date.AddMonths(1))日历化月末规范化YearFromdate.AddYears(1)DateOnly.FromDateTime(date.AddYears(1))日历化闰日规范化源码级原理T4 模板批量生成与条件编译InDate.One乃至整个InDate.一至十系列并不是手写的而是由 T4 文本模板 InDate.SomeTimeFrom.tt 在构建期批量生成的模板用for (var i 1; i 10; i)循环生成 10 个数字类类名通过i.ToWords().Dehumanize()生成即数字转英文单词one…ten后再反人类化Dehumanize为 PascalCase 标识符于是得到One、Two、…Ten成员命名规则由plural i 1 ? s : 控制i 1时使用单数形式Day/Week/Month/Year这正是InDate.One与Two~Ten的关键差异——后者使用Days/Weeks/Months/Yearsi 1时使用复数形式每个数字类的模板结构完全一致1 个从现在起属性 2 个从基准日起重载方法覆盖日/周/月/年四种粒度。因此InDate.One中属性是单数命名、方法带 From 后缀的 API 形状是模板中命名与语义规则直接推导的结果。整个生成文件整体由#if NET6_0_OR_GREATER包裹这也解释了为什么DateOnly版本只在 .NET 6 目标框架上可见DateOnly类型本身自 .NET 6 起才存在。测试验证确定性路径的可验证行为InDate系列的行为由 InDateTests.cs 覆盖测试文件同样以#if NET6_0_OR_GREATER条件编译。其中与从现在起 N 天最直接相关的用例是[Fact] public void InFiveDays() { var baseDate OnDate.January.The21st; // 构造固定基准日期 var date InDate.Five.DaysFrom(baseDate); // 从基准日推进 5 天 Assert.Equal(baseDate.AddDays(5), date); // 断言与朴素 AddDays 结果一致 }这个用例揭示了两个重要事实测试刻意使用DaysFromFrom 形式而非Days属性形式——因为属性依赖UtcNow无法写出确定性的断言这从测试策略上印证了官方文档避免在确定性代码中使用无 From 属性的告诫DaysFrom的语义就是朴素的AddDays(n)测试直接以baseDate.AddDays(5)作为期望值做等价验证说明该 API 是DateOnly原生方法的可读性包装而非引入任何额外规则。InDate.One的DayFrom/WeekFrom/MonthFrom/YearFrom遵循完全相同的模式AddDays(1)、AddDays(7)、AddMonths(1)、AddYears(1)因此可推得其行为与测试预期一致。实战建议与注意事项确定性与时区追求确定性在单元测试、定时任务、报表生成等场景中一律使用DayFrom(date)/MonthFrom(date)等 From 方法并传入固定基准日期避免读取UtcNow的属性形式明确时区边界属性基于DateTime.UtcNow计算当前时刻跨时区业务请自行换算或以本地基准日期 From 方法替代DateOnly 转换当上游数据是DateTime如数据库读取值时直接用DayFrom(DateTime)重载即可无需手工DateOnly.FromDateTime。日历化与月末/闰日边界MonthFrom与YearFrom继承AddMonths/AddYears的规范化行为1 月 31 日 1 月 → 2 月 28/29 日2024-02-29 1 年 → 2025-02-28。如果你的业务需要保月底或保闰日的语义例如订阅到期日需要自行补充修正逻辑InDate.One不提供该能力对比之下DayFrom/WeekFrom是固定天数运算不存在规范化问题跨月、跨年边界都只是自然日的累加。与时间部分的取舍DateOnly返回值意味着结果不含时分秒。需要保留精确时间点例如此刻 24 小时后的那一瞬间时应改用返回DateTime的 In.One需要某月某日这种纯日历值时InDate.One才是贴切选择。相关文档与源码导航API 参考Humanizer.InDate.One.md本文主体文档、Humanizer.InDate.md、Humanizer.In.One.md使用场景fluent-dates-and-time-spans.mdx含 Fluent Date 的定位与 Pitfall 说明源码实现InDate.SomeTimeFrom.csOne类定义于 L6-L83、In.SomeTimeFrom.csDateTime版本对照、InDate.SomeTimeFrom.ttT4 生成模板、InDate.csTheYear等配套 API测试用例InDateTests.cs、InTests.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 InDate.One 完整解析用 DateOnly 实现1 天后/周后/月后/年后的流畅日期计算Humanizer InDate.One 完整解析用 DateOnly 实现1 天后/周后/月后/年后的流畅日期计算 本文以 Humanizer 的 Fl开发工具SadTalker音频驱动面部动画从入门到精通的实战指南SadTalker音频驱动面部动画从入门到精通的实战指南 在AI视频生成领域让静态图像开口说话已不再是科幻场景。SadTalker作为CVPR 2023开发工具Humanizer InDate.Two 流畅日期 API 指南用 DateOnly 优雅表达从现在起两天/两周/两月/两年Humanizer InDate.Two 流畅日期 API 指南用 DateOnly 优雅表达从现在起两天/两周/两月/两年 本篇技术指南聚焦于 .NET开发工具上一篇如何快速搭建家庭游戏串流服务器Sunshine完全配置指南下一篇9大网盘直链下载助手告别限速烦恼获取真实下载地址创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考