0

I'm working with an ASP.Net backend. I'm saving all my dates from the client side to the database in UTC time.

I have a function in the backend that exports some records and I would like to convert the dates extracted, from UTC time to the user's local time before displaying them.

I have tried tons of solutions proposed here on StackOverflow, but none of them seem to convert the date to local time, even though this works when displaying some of these dates on the client.I suspect the server already thinks the date is in local time, but I'm not sure how else to solve it.

Below are the different solutions I have tried:

//1.

var alertTime = record.TimeRecorded.GetValueOrDefault().ToLocalTime().ToString("hh:mm tt");


// 2.
var alertTime = record.TimeRecorded;

 if (alertTime.HasValue)
    {
      var timeInUtc = TimeZoneInfo.ConvertTimeToUtc(alertTime.Value);
     string alertTimeToLocalTime = timeInUtc.ToLocalTime().ToString("hh:mm tt");

    }

 //alertTimeToLocalTime is still in UTC time here

// 3.

if (alertTime.HasValue)
    {
        var localTime = TimeZoneInfo.ConvertTimeFromUtc(timeInUtc, TimeZoneInfo.Local);
       string alertTimeToLocalTime = localTime.ToString("hh:mm tt");

    }

None of these have managed to convert the alertTime to local time.

Am I missing something?

EDIT

//4. Another approach I had already tried which didn't work as well

var alertTime = DateTime.SpecifyKind(record.TimeRecorded.GetValueOrDefault(), DateTimeKind.Utc);
alertTimeToLocalTime = alertTime.ToLocalTime().ToString("hh:mm tt");
naffie
  • 679
  • 1
  • 12
  • 29
  • Check out https://stackoverflow.com/questions/179940/convert-utc-gmt-time-to-local-time top answer – Hubbs Aug 24 '17 at 16:28
  • @Hubbs Unfortunately I already tried this and I still get the final date i UTC time instead if local time. I have added an edit with a 4th approach which shows this implementation. – naffie Aug 24 '17 at 17:45

2 Answers2

1

It's because your DateTime's Kind is either Local or Unspecified. See the documentation for ToLocalTime():

Starting with the .NET Framework version 2.0, the value returned by the ToLocalTime method is determined by the Kind property of the current DateTime object. The following table describes the possible results.

  • Utc - This instance of DateTime is converted to local time.

  • Local - No conversion is performed.

  • Unspecified - This instance of DateTime is assumed to be a UTC time, and the conversion is performed as if Kind were Utc.

You can use the SpecifyKind method to set the Kind prior to doing the conversion.

Community
  • 1
  • 1
  • unfortunately I had already tried this as well and it didn't work either. I have added it as approach no.4 to my question above to show you how I did it. – naffie Aug 24 '17 at 17:36
  • Hmmmm! Curious. I have no idea then :( –  Aug 24 '17 at 17:45
1

You said:

... from UTC time to the user's local time ...

Nothing in ASP.Net will tell you the user's local time zone. Calling ToLocalTime will convert from UTC to the server's time zone (unless the .Kind is already DateTimeKind.Local).

In many cases, the best practice of setting the server's time zone to UTC will mean that you will see no change with ToLocalTime or ToUniversalTime, other than the kind. And since the server's time zone is irrelevant in most cases, this is not the correct approach.

Instead, you either need to know the user's time zone through some other mechanism (such as them selecting it in your application) so you can use the TimeZoneInfo.ConvertTime (or Noda Time) to convert server-side, or you need to send UTC time down to the client and do the utc-to-local in JavaScript (since the browser is running in the user's time zone).

In general, any use of "local time" in a server application (such as ASP.NET) should be avoided. This includes ToLocalTime, ToUniversalTime, DateTimeKind.Local, TimeZoneInfo.Local, DateTime.Now, and a few other miscellaneous things.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • You're absolutely right Matt with this "... In many cases, the best practice of setting the server's time zone to UTC will mean that you will see no change with ToLocalTime or ToUniversalTime, other than the kind "... So I decided to get the offset from UTC from my application, then pass this to the backend and I add it to the 'alertTime' object using 'AddHours'. – naffie Aug 25 '17 at 06:31
  • Careful with that. The offset will have to be specific for that particular timestamp. Otherwise it won't account for offset changes within a time zone, such as for daylight saving time. – Matt Johnson-Pint Aug 25 '17 at 14:49
  • A better idea is to get the actual client time zone id, not just the offset. – Matt Johnson-Pint Aug 25 '17 at 14:49