☰
Humanizer InDate.Seven 指南:用 7 天/周/月/年构建 DateOnly 日期偏移
2026/9/25 5:20:14 网站建设 项目流程
  • 开发工具

【免费下载链接】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
点击查看免费下载

本篇技术指南以 Humanizer 的InDate.Seven类为核心,系统讲解 Humanizer FluentDate API 中"从现在起 7 天、7 周、7 个月、7 年之后"这一组日期计算能力:包括 4 个静态属性(Days、Weeks、Months、Years)与 8 个静态方法(DaysFrom等,各自提供DateOnly与DateTime两种重载)。读完本文,你将掌握InDate.Seven每个成员的确切签名、返回语义与底层实现原理,并能与In(基于DateTime的兄弟类)、InDate.Five等相邻 API 对照使用,写出可读性更强的日期偏移代码。

InDate.Seven 是什么:FluentDate 中的"七"号门面

Humanizer 提供了一组以自然语言命名的 FluentDate API,让日期计算代码读起来像一句英文短语。InDate.Seven是其中专门表达"7"这个数量单位的嵌套静态类,命名空间为Humanizer:

public static class InDate.Seven

从继承关系看,它直接继承自System.Object(InDate是一个public partial class,内部嵌套了一组数字类One到Ten)。与返回DateTime的In.Seven不同,InDate.Seven的全部成员都返回System.DateOnly——只携带"年/月/日",不携带时刻与时区信息,适用于日历日级别的计算场景。

需要特别注意的是,InDate系列的源码被#if NET6_0_OR_GREATER条件编译指令包裹(见 InDate.SomeTimeFrom.cs),因为DateOnly是 .NET 6 才引入的 BCL 类型。也就是说,InDate.Seven仅在 .NET 6 及更高版本的运行时可用;面向旧版本框架的项目应改用In.Seven(返回DateTime,定义于 In.SomeTimeFrom.cs)。

四个静态属性:从"现在"起算的日期

InDate.Seven暴露了 4 个只读静态属性,全部以DateTime.UtcNow(UTC 当前时刻)为基准向后偏移,再经DateOnly.FromDateTime截取日期部分。下表汇总了每个属性的语义与底层调用:

属性含义返回类型底层实现(对应 InDate.SomeTimeFrom.cs)
Days7 天后的今天System.DateOnlyDateOnly.FromDateTime(DateTime.UtcNow.AddDays(7))
Weeks7 周后的今天System.DateOnlyDateOnly.FromDateTime(DateTime.UtcNow.AddDays(49))
Months7 个月后的今天System.DateOnlyDateOnly.FromDateTime(DateTime.UtcNow.AddMonths(7))
Years7 年后的今天System.DateOnlyDateOnly.FromDateTime(DateTime.UtcNow.AddYears(7))

使用方式非常简单:

using Humanizer; DateOnly sevenDaysLater = InDate.Seven.Days; // 例如 2026-09-24 → 2026-10-01 DateOnly sevenWeeksLater = InDate.Seven.Weeks; // 49 天后 DateOnly sevenMonthsLater = InDate.Seven.Months; // 7 个自然月后 DateOnly sevenYearsLater = InDate.Seven.Years; // 7 年后

两个细节值得留意:

  1. UTC 基准:属性基于DateTime.UtcNow计算,而不是本地时间。如果调用方期望"本地时区的 7 天后",结果可能与本地日历相差一天(取决于时区偏移),这一点从源码中的DateTime.UtcNow调用可以得到直接印证。
  2. 周 = 自然日叠加:Weeks不是调用AddDays(7 * 7)之外的任何"周"语义,而是纯粹的AddDays(49),与Days一样按日历日推进。

八个静态方法:从"指定日期"起算

除了基于当前时刻的属性,InDate.Seven还提供 8 个静态方法,允许以任意给定日期为基准计算偏移。每个时间单位都有DateOnly重载与DateTime重载两个版本,完整清单如下:

DaysFrom —— 7 天后的日期

public static System.DateOnly DaysFrom(System.DateOnly date); public static System.DateOnly DaysFrom(System.DateTime date);
  • DaysFrom(DateOnly date):返回date.AddDays(7),直接对DateOnly做天数加法。
  • DaysFrom(DateTime date):返回DateOnly.FromDateTime(date.AddDays(7)),先对DateTime加 7 天,再截取日期部分。

WeeksFrom —— 7 周后的日期

public static System.DateOnly WeeksFrom(System.DateOnly date); public static System.DateOnly WeeksFrom(System.DateTime date);
  • WeeksFrom(DateOnly date):返回date.AddDays(49)。
  • WeeksFrom(DateTime date):返回DateOnly.FromDateTime(date.AddDays(49))。

MonthsFrom —— 7 个月后的日期

public static System.DateOnly MonthsFrom(System.DateOnly date); public static System.DateOnly MonthsFrom(System.DateTime date);
  • MonthsFrom(DateOnly date):返回date.AddMonths(7),遵循"自然月"语义(例如 1 月 31 日 + 7 个月,会按 .NET 的AddMonths规则做月末截断)。
  • MonthsFrom(DateTime date):返回DateOnly.FromDateTime(date.AddMonths(7))。

YearsFrom —— 7 年后的日期

public static System.DateOnly YearsFrom(System.DateOnly date); public static System.DateOnly YearsFrom(System.DateTime date);
  • YearsFrom(DateOnly date):返回date.AddYears(7),闰日(2 月 29 日)会按AddYears的规则收敛。
  • YearsFrom(DateTime date):返回DateOnly.FromDateTime(date.AddYears(7))。

典型用法:

using Humanizer; DateOnly dueDate = new(2026, 9, 24); DateOnly newDate1 = InDate.Seven.DaysFrom(dueDate); // 2026-10-01 DateOnly newDate2 = InDate.Seven.WeeksFrom(dueDate); // 2026-11-12 DateOnly newDate3 = InDate.Seven.MonthsFrom(dueDate); // 2027-04-24 DateOnly newDate4 = InDate.Seven.YearsFrom(dueDate); // 2033-09-24 // DateTime 重载:自动剥掉时刻,只保留日期 DateOnly newDate5 = InDate.Seven.DaysFrom(new DateTime(2026, 9, 24, 15, 30, 0)); // 2026-10-01

DateOnly 与 DateTime 两种重载的取舍

同一单位出现两个重载并非冗余,而是对应两种常见调用场景:

  • 传入DateOnly:输入本身就只有日历语义,方法内部直接调用DateOnly.AddDays / AddMonths / AddYears,不经过任何转换,路径最直接(源码见 InDate.SomeTimeFrom.cs)。
  • 传入DateTime:输入携带时刻(甚至Kind属性),方法先用Add*完成偏移,再通过DateOnly.FromDateTime丢弃时刻部分。这样设计保证了"无论传入什么时刻,结果永远是纯日期"。

如果你的代码上游只有DateTime(例如从数据库或DateTime.Now获取的值),可以直接使用DateTime重载而无需手动DateOnly.FromDateTime转换;如果上游已经是DateOnly(.NET 6+ 的日历型数据),则优先选择DateOnly重载,语义更精确、零转换开销。

源码深挖:T4 模板如何批量生成 One 到 Ten

InDate.Seven并不是手写一次就完事,它与InDate.One到InDate.Ten全部由同一个 T4 文本模板批量生成。打开 InDate.SomeTimeFrom.tt 可以看到核心循环逻辑:

for (var i = 1; i <= 10; i++) { var plural = i > 1 ? "s" : ""; // 类名通过 i.ToWords().Dehumanize() 生成:1 → One、7 → Seven public static class <#= i.ToWords().Dehumanize() #> { // Days / Weeks / Months / Years 及其 From 方法 } }

这个模板揭示了几个工程细节:

  1. 类名自动生成:i.ToWords()把数字转成英文单词(7→seven),再经Dehumanize()变成 PascalCase 的Seven,最终得到InDate.Seven。
  2. 单复数约定:One内部的成员是单数形式(Day、Week、Month、Year),而Two到Ten(含Seven)统一使用复数形式(Days、Weeks、Months、Years)。模板中的plural变量正是为此而设。
  3. 周数按天折算:Weeks的模板代码是DateTime.UtcNow.AddDays(i * 7),因此Seven.Weeks固定等于AddDays(49),与手写实现完全一致。
  4. 配套的 DateTime 版本:同目录下的 In.SomeTimeFrom.cs(及对应的 In.SomeTimeFrom.tt)用同样的模板思路生成In.One到In.Ten,但返回类型是DateTime而非DateOnly,两个门面类互为补充。

测试验证:生成代码的行为契约

仓库测试对这批生成的相对日期 API 做了系统性的契约校验,可作为使用时的行为依据:

  • InDateTests.cs 中的InFiveDays用例验证了组合用法:先用OnDate.January.The21st构造基准日期,再调用InDate.Five.DaysFrom(baseDate),断言结果等于baseDate.AddDays(5)——InDate.Seven的方法族遵循完全相同的偏移契约。
  • GeneratedFluentDateTests.cs 通过反射遍历InDate下所有嵌套类型:InDateRelativeDatePropertiesReturnExpectedUtcOffsets在调用前后各取一次DateTime.UtcNow,断言属性返回值落在[Add(before, amount, unit), Add(after, amount, unit)]区间内;InDateRelativeDateOnlyMethodsReturnExpectedOffsetsFromProvidedDate与InDateRelativeDateTimeMethodsReturnExpectedOffsetsFromProvidedDateTime则分别验证两类From方法。其中RelativeAmounts字典把"Seven"映射为7(见 GeneratedFluentDateTests.cs),正是这套反射校验的数据来源。

使用注意与延伸阅读

  • 适用框架:InDate.Seven依赖DateOnly,仅存在于 .NET 6 及以上目标框架;In.Seven则面向所有框架版本。
  • 时区语义:四个属性基于 UTC 计算;需要本地时区语义时,请使用From方法并传入本地日期。
  • 月份/年份边界:Months、Years沿用 .NETAddMonths/AddYears的边界收敛规则(如月末、闰日),不会抛异常。
  • 相邻 API:本文档同属 FluentDate 系列 API 文档,可对照InDate的其他数字类(如 InDate.Five)与InDate的月份类(如 InDate.January 相关页面);需要"每年/每月的某个具体日期"时,可配合 InDate.cs 中的TheYear(int year)使用;若追求DateTime语义,参考 In.Seven。

一句话总结:InDate.Seven把"7 天/周/月/年后的日期"这一高频计算封装成自然语言级 API——用属性表达"从现在起",用From方法表达"从指定日期起",两者都返回纯DateOnly,让日期偏移代码既清晰又不易出错。

  • 开发工具

【免费下载链接】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
点击查看免费下载
上一篇:CANN Runtime Stream 资源预算实战:从可用 Stream 查询到 Vector Core 限制的线程绑定
下一篇:【免费下载】 HLW8110/HLW8112电压电流电量采集芯片全套资料:助力高效能电力监测

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询