Coder Perfect

Convert time from UTC/GMT to local time.

Problem

For a web-service client, we’re working on a C# application. This program will run on Windows XP computers.

A DateTime field is one of the fields returned by the web service. The server returns a field in GMT format, which means it ends with a “Z.”

We discovered, however, that.NET appears to perform some sort of implicit conversion, because the clock was always 12 hours off.

The following code example overcomes this to some extent by eliminating the 12-hour discrepancy, however it does not take into account New Zealand daylight saving time.

CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);            

According to this website, on this date:

How will we cope with the extra hour? Is this something that can be done programmatically or is it a setting on the PCs?

Asked by rbrayb

Solution #1

DateTime is useful for strings like 2012-09-19 01:27:30.000. Parse has no way of knowing what time zone the date and time are in.

DateTime has a Kind attribute that can be set to one of three different time zones:

NOTE DateTimeOffset should be used if you want to represent a date/time that isn’t UTC or your local time zone.

So, to answer your question about the code:

DateTime convertedDate = DateTime.Parse(dateStr);

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified

Tell it what kind it is because you say you know.

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr),
    DateTimeKind.Utc);

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc

You can now simply call ToLocalTime: once the system has determined that it is in UTC time.

DateTime dt = convertedDate.ToLocalTime();

This will provide you with the desired outcome.

Answered by Drew Noakes

Solution #2

If you’re using.NET 3.5, I’d recommend utilizing the System.TimeZoneInfo class. See http://msdn.microsoft.com/library/system.timezoneinfo.aspx for further information. This should accurately account for the changes in daylight savings time.

// Coordinated Universal Time string from 
// DateTime.Now.ToUniversalTime().ToString("u");
string date = "2009-02-25 16:13:00Z"; 
// Local .NET timeZone.
DateTime localDateTime = DateTime.Parse(date); 
DateTime utcDateTime = localDateTime.ToUniversalTime();

// ID from: 
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone"
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx
string nzTimeZoneKey = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey);
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);

Answered by Daniel Ballinger

Solution #3

TimeZone.CurrentTimeZone.ToLocalTime(date);

Answered by coder1

Solution #4

DateTime objects have the default Kind of Unspecified, which is presumed to be UTC for the purposes of ToLocalTime.

To obtain the local time of an Unspecified DateTime object, simply follow these steps:

convertedDate.ToLocalTime();

It is not essential to change the DateTime’s Kind from Unspecified to UTC. For the sake of ToLocalTime, unspecified is considered to be UTC: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

Answered by CJ7

Solution #5

I know this is an older question, but I ran into a similar situation, and I wanted to share what I had found for future searchers, possibly including myself :).

DateTime. See here for an illustration of how Parse() might be challenging.

If the DateTime comes from a Web service or another established source, you might wish to use something like

DateTime.ParseExact(dateString, 
                   "MM/dd/yyyy HH:mm:ss", 
                   CultureInfo.InvariantCulture, 
                   DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)

or, even better,

DateTime.TryParseExact(...)

The AssumeUniversal option notifies the parser that the date/time is already UTC; the AssumeUniversal and AdjustToUniversal flags tell it not to convert the result to “local” time, which it will try by default. (In any case, I attempt to deal with UTC only in the business / application / service layer(s).) However, skipping the conversion to local time speeds things up significantly (by 50% or more in my tests, see below.)

This is what we were doing previously:

DateTime.Parse(dateString, new CultureInfo("en-US"))

We profiled the app and discovered that DateTime.Parse accounted for a large portion of CPU use. (The CultureInfo constructor, however, did not contribute significantly to CPU utilization.)

As a result, I created a terminal software that parses a date/time string 10,000 times in various ways. The bottom line is that Parse() takes 10 seconds. ParseExact() is a function that returns the exact value (converting to local) 20-45 milliseconds ParseExact() is a function that returns the exact value (not converting to local) 10-15 milliseconds… and yes, the Parse() results are in seconds, whereas the others are in milliseconds.

Answered by David

Post is based on https://stackoverflow.com/questions/179940/convert-utc-gmt-time-to-local-time