Skip to main content
Version: 4.0 (next)

Humanize relative dates and times

Relative humanization compares a temporal value with a known base and returns text such as yesterday, 3 hours ago, or a month from now. Pass both the comparison base and culture when output must be deterministic. Choose the overload that preserves the semantics of DateTime, DateTimeOffset, DateOnly, or TimeOnly.

Example​

The example compares two UTC DateTime values and never reads the machine clock. The same explicit CultureInfo argument is available on the DateTimeOffset, DateOnly, and TimeOnly overloads:

Program.cs
using System.Globalization;
using Humanizer;

var culture = CultureInfo.GetCultureInfo("en-US");
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;

var comparison = new DateTime(2025, 1, 20, 12, 0, 0, DateTimeKind.Utc);
var relative = comparison.AddDays(-1).Humanize(
utcDate: true,
dateToCompareAgainst: comparison,
culture: culture);
var offsetComparison = new DateTimeOffset(comparison);
var offsetRelative = offsetComparison.AddDays(-1).Humanize(offsetComparison, culture);
var dateOnlyComparison = new DateOnly(2025, 1, 20);
var dateOnlyRelative = dateOnlyComparison.AddDays(-1).Humanize(dateOnlyComparison, culture);
var timeOnlyComparison = new TimeOnly(12, 0);
var timeOnlyRelative = timeOnlyComparison.AddMinutes(1).Humanize(timeOnlyComparison, culture: culture);
var duration = TimeSpan.FromMinutes(125).Humanize(precision: 2, culture: culture);

Console.WriteLine($"DateTime: {relative}");
Console.WriteLine($"DateTimeOffset: {offsetRelative}");
Console.WriteLine($"DateOnly: {dateOnlyRelative}");
Console.WriteLine($"TimeOnly: {timeOnlyRelative}");
Console.WriteLine($"Duration: {duration}");
Output
DateTime: yesterday
DateTimeOffset: yesterday
DateOnly: yesterday
TimeOnly: a minute from now
Duration: 2 hours, 5 minutes

Choose the temporal type​

TypeComparison meaning
DateTimeLocal or UTC behavior selected by utcDate and Kind
DateTimeOffsetTwo offset-aware instants
DateOnlyCalendar dates without a time of day
TimeOnlyTimes of day without a calendar date

Nullable overloads return the locale’s “never” phrase for null. That is useful for optional activity timestamps but should not replace explicit missing-value handling in domain logic.

Configure thresholds once​

The default strategies choose familiar boundaries such as “yesterday.” PrecisionDateTimeHumanizeStrategy and its sibling strategies use a precision factor when applications need more gradual thresholds. Assign a strategy through Configurator once during startup.

Keep local and UTC values separate​

Do not compare a local DateTime with a UTC base accidentally. Humanizer converts the injected comparison according to utcDate; mixed Kind values can move the boundary. TimeOnly has no date context, so a comparison around midnight cannot know whether the intended event was yesterday or tomorrow.