3

I have this code:

Configurator.DateTimeHumanizeStrategy = new PrecisionDateTimeHumanizeStrategy(.75);
var dateTime1 = DateTime.UtcNow.AddYears(2).AddMonths(-5);
var text1 = dateTime1.Humanize();

In the text1 variable I get "one year from now". But this is not very accurate. Is there any way to get "one year and seven months from now"?

Update 1:

Solution @Daniel Hoffman has some problems, for example if my date is in the past:

//UtcNow is 11.07.2021
var dateTime6 = new DateTime(2021, 4, 24);
TimeSpan dateTimeSpan6 = dateTime6 - DateTime.UtcNow;
var text6 = dateTime6.Humanize();
string textSpan6 = dateTimeSpan6.Humanize(maxUnit: TimeUnit.Year, precision: 2);

then I get "2 months, 11 weeks" which contains basically the same information twice but in different units.

Update 2:

I have fixed the problem with dates in the past, by using Duration() method:

var timeSpan = date - DateTime.UtcNow;

return timeSpan.Duration().Humanize(maxUnit: TimeUnit.Year, precision: 2, minUnit: TimeUnit.Day);
robocik
  • 101
  • 7
  • 20
  • You could calculate the number of months between the two dates, and if the result is a multiple of 12, display the number of years, and otherwise display the number of month (or years+months). see also: https://stackoverflow.com/questions/1525990/calculating-the-difference-in-months-between-two-dates/1526004 – Luuk Jul 10 '21 at 11:17

2 Answers2

1

[Edit]: Using TimeSpan will allow you to specify the precision of your period, but you will lose the ability to have "yesterday" or "tomorrow", and it omits the " ago" or " from now", all of which are localized. A partial workaround would be to use the TimeSpan.Humanize method for TimeSpans less than 366 days and DateTime.Humanize otherwise. And if it's only going to be used in one language, the user can append the appropriate text depending on if the timespan is negative.

You can use the precision parameter with a TimeSpan:

TimeSpan periodFromNow = DateTime.UtcNow.AddYears(2).AddMonths(-5) - DateTime.UtcNow;

Then:

string myPeriodFromNow = periodFromNow.Humanize(maxUnit: TimeUnit.Year, precision: 2);

Other examples:

TimeSpan.FromDays(486).Humanize(maxUnit: TimeUnit.Year, precision: 7) => "1 year, 3 months, 29 days" // One day further is 1 year, 4 month
TimeSpan.FromDays(517).Humanize(maxUnit: TimeUnit.Year, precision: 7) => "1 year, 4 months, 30 days" // This month has 30 days and one day further is 1 year, 5 months

See also: https://github.com/Humanizr/Humanizer#humanize-timespan

Daniël J.M. Hoffman
  • 1,539
  • 10
  • 16
0

It seems like its not currently possible in Humanizer to do what you want.

Check out this method PrecisionHumanize() on line 102, if the amount of days exceeds 365 then only years will be returned. And in general it seems like only one type of length of time can be returned, there is no years and months or minutes and seconds, just the largest one.

But check out another library called NodaTime it might be able to do what you want.

Here is a link to a different question similar to yours.

golakwer
  • 355
  • 1
  • 4