
开发工具【免费下载链接】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点击查看免费下载导读PrepositionsExtensions是 Humanizer 库中一组面向System.DateTime的静态扩展方法用介词式的 APIAt、AtMidnight、AtNoon、In来刻画日期与时间之间的空间/时间关系把构造某个时刻这一常见操作从冗长的new DateTime(...)写法中解放出来。本文以 version-3.0.1 版 API 文档 为骨架结合当前仓库源码与测试完整讲解这四个方法的签名、参数语义、返回值与底层实现并展示它们与In、On、InDate、OnDate等 FluentDate 家族 API 的组合用法帮助你写出更接近自然语言、可读性更高的日期时间代码。一、类概览什么是 PrepositionsExtensions在 Humanizer 中PrepositionsExtensions被定位为与空间或时间关系相关的DateTime扩展方法官方 XML 注释原文DateTime extensions related to spatial or temporal relations定义于 src/Humanizer/FluentDate/PrepositionsExtensions.cs。它是一个public static class继承链为System.Object→PrepositionsExtensions全部成员都是public static扩展方法因此在引入using Humanizer;命名空间后即可直接以date.At(14, 30)这样的点语法调用。四个方法及其签名如下方法签名作用At(this DateTime date, int hour, int min 0, int second 0, int millisecond 0)保留date的年月日把时刻设为指定的小时/分钟/秒/毫秒AtMidnight(this DateTime date)把时刻设为当天午夜00:00:00AtNoon(this DateTime date)把时刻设为当天正午12:00:00In(this DateTime date, int year)保留date的月日时分秒毫秒把年份设为指定值说明本文所述为当前仓库v3.0.1 版本线的实现。若你在更新的版本中使用请以该版本的 API 文档 为准。二、At指定某个时刻签名与参数语义public static System.DateTime At(this System.DateTime date, int hour, int min 0, int second 0, int millisecond 0);At基于传入的date构造一个新DateTime仅替换时间部分hour必填目标小时0–23min可选默认0目标分钟second可选默认0目标秒millisecond可选默认0目标毫秒。由于后三个参数都有默认值实际使用时可以按需省略date.At(9)表示当天 09:00:00.000date.At(14, 30)表示当天 14:30:00.000。底层实现源码中At是一次纯粹的构造调用PrepositionsExtensions.cs#L12-L13public static DateTime At(this DateTime date, int hour, int min 0, int second 0, int millisecond 0) new(date.Year, date.Month, date.Day, hour, min, second, millisecond);它保留了date.Year/Month/Day并整体重建时分秒毫秒。这意味着返回的是新的DateTime实例原date不受影响DateTime本身是值类型这也保证了纯函数式语义传入非法的小时/分钟值如hour 24、min 60会像new DateTime(...)一样抛出ArgumentOutOfRangeExceptionKind属性Local/Utc/Unspecified不会被保留——这一点与In相同下文会进一步说明。实战示例using Humanizer; var date new DateTime(2025, 1, 20, 9, 0, 0); // 2025-01-20 09:00 var atNine date.At(9); // 2025-01-20 09:00:00.000 var atHalfPastTwo date.At(14, 30); // 2025-01-20 14:30:00.000 var atCustom date.At(23, 59, 59, 999); // 2025-01-20 23:59:59.999三、AtMidnight 与 AtNoon两个约定时刻快捷方式AtMidnight与AtNoon是At的两个特化形式分别把时刻固定为午夜与正午public static System.DateTime AtMidnight(this System.DateTime date); public static System.DateTime AtNoon(this System.DateTime date);底层实现两个方法内部直接委托给AtPrepositionsExtensions.cs#L18-L25public static DateTime AtMidnight(this DateTime date) date.At(0); public static DateTime AtNoon(this DateTime date) date.At(12);即AtMidnight等价于date.At(0)00:00:00.000AtNoon等价于date.At(12)12:00:00.000。测试佐证仓库测试 tests/Humanizer.Tests/FluentDate/PrepositionTests.cs 精确锁定了这两个方法的语义[Fact] public void AtMidnight() { var now DateTime.Now; var midnight now.AtMidnight(); Assert.Equal(new(now.Year, now.Month, now.Day), midnight); } [Fact] public void AtNoon() { var now DateTime.Now; var noon now.AtNoon(); Assert.Equal(new(now.Year, now.Month, now.Day, 12, 0, 0), noon); }注意测试断言中AtMidnight期望值是new(now.Year, now.Month, now.Day)未指定时分秒即 00:00:00而AtNoon期望值是new(now.Year, now.Month, now.Day, 12, 0, 0)与源码实现完全对应。实战示例var today DateTime.Today; var midnight today.AtMidnight(); // 今天 00:00:00.000 var noon today.AtNoon(); // 今天 12:00:00.000 // 与 At 组合把某一天变成某一天的某个时刻 var deadline new DateTime(2025, 12, 31).AtNoon(); // 2025-12-31 12:00:00四、In(year)把日期搬到指定年份签名与参数语义public static System.DateTime In(this System.DateTime date, int year);In基于传入的date构造一个新DateTime把年份替换为year同时保留原有的月、日、时、分、秒、毫秒。底层实现源码如下PrepositionsExtensions.cs#L30-L31public static DateTime In(this DateTime date, int year) new(year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond);与 AddYears 的关键区别从实现可以看出In不是AddYears(year - date.Year)的别名两者行为差异显著In(year)走new DateTime(year, month, day, ...)构造路径如果目标年份不存在该月日例如把闰年 2 月 29 日搬到平年会直接抛出ArgumentOutOfRangeException即失败要响亮AddYears则会做日历归一化normalization例如 2024-02-29AddYears(1)会得到 2025-02-28。这一点在网站文档 website/docs/scenarios/fluent-dates-and-time-spans.mdx 中被明确点出MonthsFromandYearsFrominheritAddMonths/AddYearsnormalization, so moving February 29 into a non-leap year produces February 28. By contrast,date.In(year)reconstructs the same month and day in the requested year and throws when that date does not exist.MonthsFrom/YearsFrom继承AddMonths/AddYears的归一化把 2 月 29 日搬到非闰年得到 2 月 28 日而date.In(year)会在目标年份重建相同的月日当该日期不存在时抛出异常。测试佐证PrepositionTests.cs#L19-L25 验证了In的完整保留语义[Fact] public void InYear() { var now DateTime.Now; var in2012 now.In(2012); Assert.Equal(new(2012, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond), in2012); }实战示例var birthday new DateTime(2025, 6, 15, 10, 30, 0); var sameDayLastYear birthday.In(2024); // 2024-06-15 10:30:00五、与 FluentDate 家族 API 组合使用PrepositionsExtensions并不孤立存在它与In、On、InDate、OnDate同属 FluentDate 模块共同构成一套自然语言式日期构造体系。In年月与从现在起src/Humanizer/FluentDate/In.Months.cs 提供In.January、In.AprilOf(2025)等属性/方法January表示今年 1 月 1 日基于DateTime.UtcNow.YearAprilOf(2025)表示2025 年 4 月 1 日src/Humanizer/FluentDate/In.SomeTimeFrom.cs 提供In.Two.MonthsFrom(startingPoint)、In.One.Day等基于AddSeconds/AddMinutes/AddHours/AddDays/AddMonths/AddYears的偏移计算src/Humanizer/FluentDate/In.cs 提供In.TheYear(2025)表示2025 年 1 月 1 日。On指定某月的第 N 天src/Humanizer/FluentDate/On.Days.cs 提供On.January.The3rd、On.January.The(dayNumber)等成员表示今年某月的第 N 天基于DateTime.Now.Year。组合示例网站示例工程 website/docs/_examples/scenarios-fluent-dates/Program.cs 展示了这些 API 与PrepositionsExtensions的典型协作using Humanizer; var startingPoint new DateTime(2025, 1, 20, 9, 0, 0); var twoMonthsLater In.Two.MonthsFrom(startingPoint); // 2025-03-20 09:00AddMonths 偏移 var appointment In.AprilOf(2025).AddDays(2).At(14, 30); // 2025-04-03 14:30At 指定时刻其中In.AprilOf(2025)构造出 2025-04-01AddDays(2)得到 2025-04-03最后At(14, 30)把时刻设为 14:30——整个表达式读起来就像一句自然语言在 2025 年 4 月 3 日 14:30 有一个约会。DateOnly对应物InDate、OnDate提供了InDate.AprilOf(2025)、OnDate.April.The3rd等成员在支持DateOnly的框架上可生成相应的DateOnly值见网站文档 fluent-dates-and-time-spans.mdx。六、易错点与最佳实践At/In不保留DateTimeKind两个方法都通过new DateTime(...)重建实例构造出的值Kind为Unspecified。若业务代码依赖date.Kind例如需要Utc进行序列化请在调用后自行补回DateTime.SpecifyKind(...)。In与AddYears语义不同需要把日期搬到某年且目标日期一定存在时用In需要年份加减且接受日历归一化时用AddYears。把闰日搬到平年会抛异常这是设计使然。非法参数会抛异常At(24, 0)、In(0)等超出DateTime合法范围的值会在构造时抛出ArgumentOutOfRangeException建议在动态传参场景如用户输入中先做范围校验。组合使用让代码自我注释优先用date.AtMidnight()/date.AtNoon()表达午夜/正午用In.AprilOf(2025).At(14, 30)表达绝对时刻避免魔法数字散落在业务代码中。注意In与In类的重名扩展方法date.In(2025)把年份改为 2025与静态类In如In.Two.MonthsFrom(...)是两回事阅读代码时注意区分上下文。七、进一步阅读API 参考Humanizer.PrepositionsExtensions.md、Humanizer.In.md、Humanizer.On.md、Humanizer.InDate.md、Humanizer.OnDate.md场景指南Fluent dates and time spans源码实现src/Humanizer/FluentDate/PrepositionsExtensions.cs、src/Humanizer/FluentDate/In.Months.cs、src/Humanizer/FluentDate/On.Days.cs测试用例tests/Humanizer.Tests/FluentDate/PrepositionTests.cs、tests/Humanizer.Tests/FluentDate/InTests.cs可运行示例website/docs/_examples/scenarios-fluent-dates/Program.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 PrepositionsExtensions 完全指南用 At / AtNoon / AtMidnight / In 优雅构造 DateTimeHumanizer PrepositionsExtensions 完全指南用 At / AtNoon / AtMidnight / In 优雅构造 DateT开发工具Humanizer PrepositionsExtensions 指南用 At、AtMidnight、AtNoon 与 In(year) 精确构造 DateTimeHumanizer PrepositionsExtensions 指南用 At、AtMidnight、AtNoon 与 In year 精确构造 DateTi开发工具Humanizer PrepositionsExtensions 指南用 At、AtNoon、AtMidnight 与 In 打造可读的 DateTime 时间构造Humanizer PrepositionsExtensions 指南用 At、AtNoon、AtMidnight 与 In 打造可读的 DateTime 时开发工具上一篇DaoCloud公开镜像仓库同步MinIO历史版本镜像的技术实践下一篇突破对象存储性能瓶颈AList内网接入优化全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考