Humanizr / Humanizer

Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Humanizing dates in time zones other than system and UTC

ryno1234 opened this issue · comments

I'm attempting to humanize a date in the local (to the user) time zone.

  1. We store dates in the DB as UTC.
  2. I want to humanize the dates in the user's local timezone.
  3. I convert the UTC dates to local var localTime = TimeZoneInfo.ConvertTimeFromUtc(utcTime, usersLocalTimeZone)
  4. Call humanizer localTime .Humanize(false, localNow)
  5. Result is very bizarre and nonsensical (at first glance)

After reviewing the source code it seems that is because the dateToCompareAgainst in is always converted either ToUniversalTime() or ToLocalTime()

    public static string Humanize(this DateTime input, bool? utcDate = null, DateTime? dateToCompareAgainst = null, CultureInfo culture = null)
    {
        var comparisonBase = dateToCompareAgainst.HasValue ? dateToCompareAgainst.Value : DateTime.UtcNow;
        utcDate ??= input.Kind != DateTimeKind.Local;
        comparisonBase = utcDate.Value ? comparisonBase.ToUniversalTime() : comparisonBase.ToLocalTime();

        return Configurator.DateTimeHumanizeStrategy.Humanize(input, comparisonBase, culture);
    }

What is the best course of action to supply 2 dates in any like-timezone and get the the time between them?

Side note: I realize there are reasons this functions like this, however perhaps it should be made more clear in the documentation how the internals work. You apparently cannot simply provide 2 dates and get the humanized value unless the dates are either UTC or Local (local meaning server's time by default). Providing DateTimes that coincide with a time zone other than UTC or Local produce unexpected results.

DateTime.ToLocalTime uses the DateTimeKind to determine if the date needs to be converted at all. I think you may be able to work around the weird behaviour by using DateTime.SpecifyKind.