Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a time expression provider to allow the user to select the predefined ones. #875

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 12 additions & 12 deletions src/Humanizer.Tests.Shared/DateHumanize.cs
Expand Up @@ -11,30 +11,30 @@ public class DateHumanize
{
private static readonly object LockObject = new object();

private static void VerifyWithCurrentDate(string expectedString, TimeSpan deltaFromNow, CultureInfo culture)
private static void VerifyWithCurrentDate(string expectedString, TimeSpan deltaFromNow, CultureInfo culture, DateTimeExpressionProvider dateTimeExpressionProvider)
{
var utcNow = DateTime.UtcNow;
var localNow = DateTime.Now;

// feels like the only way to avoid breaking tests because CPU ticks over is to inject the base date
VerifyWithDate(expectedString, deltaFromNow, culture, localNow, utcNow);
VerifyWithDate(expectedString, deltaFromNow, culture, localNow, utcNow, dateTimeExpressionProvider);
}

private static void VerifyWithDateInjection(string expectedString, TimeSpan deltaFromNow, CultureInfo culture)
private static void VerifyWithDateInjection(string expectedString, TimeSpan deltaFromNow, CultureInfo culture, DateTimeExpressionProvider dateTimeExpressionProvider)
{
var utcNow = new DateTime(2013, 6, 20, 9, 58, 22, DateTimeKind.Utc);
var now = new DateTime(2013, 6, 20, 11, 58, 22, DateTimeKind.Local);

VerifyWithDate(expectedString, deltaFromNow, culture, now, utcNow);
VerifyWithDate(expectedString, deltaFromNow, culture, now, utcNow, dateTimeExpressionProvider);
}

private static void VerifyWithDate(string expectedString, TimeSpan deltaFromBase, CultureInfo culture, DateTime baseDate, DateTime baseDateUtc)
private static void VerifyWithDate(string expectedString, TimeSpan deltaFromBase, CultureInfo culture, DateTime baseDate, DateTime baseDateUtc, DateTimeExpressionProvider dateTimeExpressionProvider)
{
Assert.Equal(expectedString, baseDateUtc.Add(deltaFromBase).Humanize(utcDate: true, dateToCompareAgainst: baseDateUtc, culture: culture));
Assert.Equal(expectedString, baseDate.Add(deltaFromBase).Humanize(false, baseDate, culture: culture));
Assert.Equal(expectedString, baseDateUtc.Add(deltaFromBase).Humanize(utcDate: true, dateToCompareAgainst: baseDateUtc, culture: culture, dateTimeExpressionProvider));
Assert.Equal(expectedString, baseDate.Add(deltaFromBase).Humanize(false, baseDate, culture: culture, dateTimeExpressionProvider));
}

public static void Verify(string expectedString, int unit, TimeUnit timeUnit, Tense tense, double? precision = null, CultureInfo culture = null, DateTime? baseDate = null, DateTime? baseDateUtc = null)
public static void Verify(string expectedString, int unit, TimeUnit timeUnit, Tense tense, double? precision = null, CultureInfo culture = null, DateTime? baseDate = null, DateTime? baseDateUtc = null, DateTimeExpressionProvider dateTimeExpressionProvider = null)
{
// We lock this as these tests can be multi-threaded and we're setting a static
lock (LockObject)
Expand Down Expand Up @@ -83,14 +83,14 @@ public static void Verify(string expectedString, int unit, TimeUnit timeUnit, Te

if (baseDate == null)
{
VerifyWithCurrentDate(expectedString, deltaFromNow, culture);
VerifyWithDateInjection(expectedString, deltaFromNow, culture);
VerifyWithCurrentDate(expectedString, deltaFromNow, culture, dateTimeExpressionProvider);
VerifyWithDateInjection(expectedString, deltaFromNow, culture, dateTimeExpressionProvider);
}
else
{
VerifyWithDate(expectedString, deltaFromNow, culture, baseDate.Value, baseDateUtc.Value);
VerifyWithDate(expectedString, deltaFromNow, culture, baseDate.Value, baseDateUtc.Value, dateTimeExpressionProvider);
}
}
}
}
}
}
192 changes: 192 additions & 0 deletions src/Humanizer.Tests/DateTimeHumanizePrecisionTimeExpressionsTests.cs
@@ -0,0 +1,192 @@
using Humanizer.Localisation;
using Xunit;

namespace Humanizer.Tests
{
[UseCulture("en-US")]
public class DateTimeHumanizePrecisionTimeExpressionsTests
{

private const double DefaultPrecision = .75;
private static readonly TimeExpressionProviderToTest _timeExpressionProvider = new TimeExpressionProviderToTest();

[Theory]
[InlineData(1, "now")]
[InlineData(749, "now")]
[InlineData(750, "for one second")]
[InlineData(1000, "for one second")]
[InlineData(1749, "for one second")]
[InlineData(1750, "for 2 seconds")]
public void MillisecondsAgo(int milliseconds, string expected)
{
DateHumanize.Verify(expected, milliseconds, TimeUnit.Millisecond, Tense.Past, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "now")]
[InlineData(749, "now")]
[InlineData(750, "in one second")]
[InlineData(1000, "in one second")]
[InlineData(1749, "in one second")]
[InlineData(1750, "in 2 seconds")]
public void MillisecondsFromNow(int milliseconds, string expected)
{
DateHumanize.Verify(expected, milliseconds, TimeUnit.Millisecond, Tense.Future, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "for one second")]
[InlineData(10, "for 10 seconds")]
[InlineData(44, "for 44 seconds")]
[InlineData(45, "for a minute")]
[InlineData(60, "for a minute")]
[InlineData(104, "for a minute")]
[InlineData(105, "for 2 minutes")]
[InlineData(120, "for 2 minutes")]
public void SecondsAgo(int seconds, string expected)
{
DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Past, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "in one second")]
[InlineData(10, "in 10 seconds")]
[InlineData(44, "in 44 seconds")]
[InlineData(45, "in a minute")]
[InlineData(60, "in a minute")]
[InlineData(104, "in a minute")]
[InlineData(105, "in 2 minutes")]
[InlineData(120, "in 2 minutes")]
public void SecondsFromNow(int seconds, string expected)
{
DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Future, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "for a minute")]
[InlineData(10, "for 10 minutes")]
[InlineData(44, "for 44 minutes")]
[InlineData(45, "for an hour")]
[InlineData(60, "for an hour")]
[InlineData(104, "for an hour")]
[InlineData(105, "for 2 hours")]
[InlineData(120, "for 2 hours")]
public void MinutesAgo(int minutes, string expected)
{
DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Past, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "in a minute")]
[InlineData(10, "in 10 minutes")]
[InlineData(44, "in 44 minutes")]
[InlineData(45, "in an hour")]
[InlineData(60, "in an hour")]
[InlineData(104, "in an hour")]
[InlineData(105, "in 2 hours")]
[InlineData(120, "in 2 hours")]
public void MinutesFromNow(int minutes, string expected)
{
DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Future, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "for an hour")]
[InlineData(10, "for 10 hours")]
[InlineData(17, "for 17 hours")]
[InlineData(18, "for one day")]
[InlineData(24, "for one day")]
[InlineData(41, "for one day")]
[InlineData(42, "for 2 days")]
[InlineData(48, "for 2 days")]
[InlineData(60, "for 2 days")]
public void HoursAgo(int hours, string expected)
{
DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Past, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "in an hour")]
[InlineData(10, "in 10 hours")]
[InlineData(18, "tomorrow")]
[InlineData(24, "tomorrow")]
[InlineData(41, "tomorrow")]
[InlineData(42, "in 2 days")]
[InlineData(48, "in 2 days")]
[InlineData(60, "in 2 days")]
public void HoursFromNow(int hours, string expected)
{
DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "for one day")]
[InlineData(10, "for 10 days")]
[InlineData(20, "for 20 days")]
[InlineData(22, "for 22 days")]
[InlineData(23, "for one month")]
[InlineData(31, "for one month")]
[InlineData(43, "for one month")]
[InlineData(53, "for 2 months")]
public void DaysAgo(int days, string expected)
{
DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Past, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "tomorrow")]
[InlineData(10, "in 10 days")]
[InlineData(20, "in 20 days")]
[InlineData(22, "in 22 days")]
[InlineData(23, "in one month")]
[InlineData(31, "in one month")]
[InlineData(43, "in one month")]
[InlineData(53, "in 2 months")]
public void DaysFromNow(int days, string expected)
{
DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Future, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "for one month")]
[InlineData(8, "for 8 months")]
[InlineData(9, "for one year")]
[InlineData(12, "for one year")]
[InlineData(19, "for one year")]
[InlineData(21, "for 2 years")]
[InlineData(24, "for 2 years")]
public void MonthsAgo(int months, string expected)
{
DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Past, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "in one month")]
[InlineData(8, "in 8 months")]
[InlineData(9, "in one year")]
[InlineData(12, "in one year")]
[InlineData(19, "in one year")]
[InlineData(21, "in 2 years")]
[InlineData(24, "in 2 years")]
public void MonthsFromNow(int months, string expected)
{
DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Future, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "for one year")]
[InlineData(2, "for 2 years")]
public void YearsAgo(int years, string expected)
{
DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Past, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}

[Theory]
[InlineData(1, "in one year")]
[InlineData(2, "in 2 years")]
public void YearsFromNow(int years, string expected)
{
DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Future, DefaultPrecision, dateTimeExpressionProvider: _timeExpressionProvider);
}
}
}
138 changes: 138 additions & 0 deletions src/Humanizer.Tests/DateTimeHumanizeSupportTimeExpressionsTests.cs
@@ -0,0 +1,138 @@
using System;
using System.Globalization;
using Humanizer.Localisation;
using Xunit;

namespace Humanizer.Tests
{
[UseCulture("en-US")]
public class DateTimeHumanizeSupportTimeExpressionsTests
{

private static readonly TimeExpressionProviderToTest TimeExpressionProvider = new TimeExpressionProviderToTest();

[Theory]
[InlineData(1, "for one second")]
[InlineData(10, "for 10 seconds")]
[InlineData(59, "for 59 seconds")]
[InlineData(60, "for a minute")]
public void SecondsFor(int seconds, string expected)
{
DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Past, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "in one second")]
[InlineData(10, "in 10 seconds")]
[InlineData(59, "in 59 seconds")]
[InlineData(60, "in a minute")]
public void SecondsIn(int seconds, string expected)
{
DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Future, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "for a minute")]
[InlineData(10, "for 10 minutes")]
[InlineData(44, "for 44 minutes")]
[InlineData(45, "for 45 minutes")]
[InlineData(59, "for 59 minutes")]
[InlineData(60, "for an hour")]
[InlineData(119, "for an hour")]
[InlineData(120, "for 2 hours")]
public void MinutesFor(int minutes, string expected)
{
DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Past, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "in a minute")]
[InlineData(10, "in 10 minutes")]
[InlineData(44, "in 44 minutes")]
[InlineData(45, "in 45 minutes")]
[InlineData(59, "in 59 minutes")]
[InlineData(60, "in an hour")]
[InlineData(119, "in an hour")]
[InlineData(120, "in 2 hours")]
public void MinutesIn(int minutes, string expected)
{
DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Future, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "for an hour")]
[InlineData(10, "for 10 hours")]
[InlineData(23, "for 23 hours")]
[InlineData(24, "for one day")]
public void HoursFor(int hours, string expected)
{
DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Past, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "in an hour")]
[InlineData(10, "in 10 hours")]
[InlineData(23, "in 23 hours")]
[InlineData(24, "tomorrow")]
public void HoursIn(int hours, string expected)
{
DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "for one day")]
[InlineData(10, "for 10 days")]
[InlineData(27, "for 27 days")]
[InlineData(32, "for one month")]
public void DaysFor(int days, string expected)
{
DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Past, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "tomorrow")]
[InlineData(10, "in 10 days")]
[InlineData(27, "in 27 days")]
[InlineData(32, "in one month")]
public void DaysIn(int days, string expected)
{
DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Future, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "for one month")]
[InlineData(10, "for 10 months")]
[InlineData(11, "for 11 months")]
[InlineData(12, "for one year")]
public void MonthsFor(int months, string expected)
{
DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Past, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "in one month")]
[InlineData(10, "in 10 months")]
[InlineData(11, "in 11 months")]
[InlineData(12, "in one year")]
public void MonthsIn(int months, string expected)
{
DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Future, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "for one year")]
[InlineData(2, "for 2 years")]
public void YearsFor(int years, string expected)
{
DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Past, dateTimeExpressionProvider: TimeExpressionProvider);
}

[Theory]
[InlineData(1, "in one year")]
[InlineData(2, "in 2 years")]
public void YearsIn(int years, string expected)
{
DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Future, dateTimeExpressionProvider: TimeExpressionProvider);
}
}
}