Compose dates and time spans fluently
Orientation
Humanizer’s numeric time-span extensions make duration constants readable, while In, On, and the date preposition extensions build calendar values. Use duration helpers for fixed elapsed time and calendar helpers for month/year arithmetic. Inject a starting date instead of relying on “now” when code or tests must be repeatable.
Example
The executable composes a 36-hour duration, adds two calendar months to a fixed date, and constructs a dated appointment:
using System.Globalization;
using Humanizer;
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
var duration = 1.5.Days();
var startingPoint = new DateTime(2025, 1, 20, 9, 0, 0);
var twoMonthsLater = In.Two.MonthsFrom(startingPoint);
var appointment = In.AprilOf(2025).AddDays(2).At(14, 30);
AssertEqual(TimeSpan.FromHours(36), duration);
AssertEqual(new DateTime(2025, 3, 20, 9, 0, 0), twoMonthsLater);
AssertEqual(new DateTime(2025, 4, 3, 14, 30, 0), appointment);
Console.WriteLine("36 hours; 2025-03-20; 2025-04-03 14:30");
static void AssertEqual<T>(T expected, T actual)
{
if (!EqualityComparer<T>.Default.Equals(expected, actual))
throw new InvalidOperationException($"Expected '{expected}', got '{actual}'.");
}
Fixed durations
Numeric values expose Milliseconds, Seconds, Minutes, Hours, Days, and Weeks. A call such as 1.5.Days() produces a TimeSpan; its day is always 24 hours.
Calendar arithmetic
In.One through In.Ten provide DaysFrom, WeeksFrom, MonthsFrom, and YearsFrom. Month and year forms delegate to DateTime or DateOnly AddMonths/AddYears: they are calendar-sized operations rather than estimated TimeSpan values, but they do not select a culture-specific Calendar.
On.April.The3rd, In.AprilOf(2025), At, AtNoon, AtMidnight, and In(year) are readable constructors around DateTime. InDate and OnDate provide corresponding DateOnly values on compatible frameworks.
Pitfall
Properties without From or Of(year) read DateTime.Now or UtcNow. Avoid them in deterministic code. MonthsFrom and YearsFrom inherit AddMonths/AddYears normalization, 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. Constructors for impossible month/day combinations also throw.
Version notes
The DateTime fluent surface and time-span extensions are available across the
documented corpus. DateOnly fluent helpers begin in 2.11.10 on compatible
target frameworks. The example uses the shared DateTime surface and runs
against the selected package.