Craig
Craig

Reputation: 36836

TimeZone Offset not calculated as expected

I have some code like this

string date = "10/06/2017 1:30:00 PM"; // UTC time
var dateValue = DateTime.ParseExact(date, "d/MM/yyyy h:mm:ss tt", CultureInfo.InvariantCulture);
string timeZone = "Eastern Standard Time"; // Offset is -5 hours
TimeZoneInfo newTime = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
var result = TimeZoneInfo.ConvertTime(dateValue, newTime).ToString("yyyy-MM-dd HH:mm");

The result output is 2017-06-09 23:30 which is two hours less than the original, not the 5 hours the offset would indicate. Any ideas?

Upvotes: 1

Views: 55

Answers (1)

Rob
Rob

Reputation: 27367

Couple of issues here:

  • Eastern Standard Time has a base offset of -5 hours. However, it experiences daylight savings time at that particular datetime

string timeZone = "Eastern Standard Time"; // Offset is -5 hours

TimeZoneInfo newTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
Console.WriteLine(newTimeZone.BaseUtcOffset); // -5
Console.WriteLine(newTimeZone.IsDaylightSavingTime(dateValue)); // True
  • ParseExact does not specifiy a DateTimeKind, and defaults to unspecified. This means it behaves as both a UTC and local time, depending on what operation you perform on it. We should be explicit here that we're talking about a UTC time:

string date = "10/06/2017 1:30:00 PM"; // UTC time
var dateValue = DateTime.ParseExact(date, 
                    "d/MM/yyyy h:mm:ss tt", 
                    CultureInfo.InvariantCulture, 
                    DateTimeStyles.AssumeUniversal);

// Although we specified above that the string represents a UTC time, we're still given 
// A local time back (equivalent to that UTC)
// Note this is only for debugging purposes, it won't change the result of the output   
dateValue = dateValue.ToUniversalTime();

Final code:

string date = "10/06/2017 1:30:00 PM"; // UTC time
var dateValue = DateTime.ParseExact(date, "d/MM/yyyy h:mm:ss tt", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);

string timeZone = "Eastern Standard Time"; // Offset is -5 hours

TimeZoneInfo newTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
Console.WriteLine(newTimeZone.BaseUtcOffset); // -5
Console.WriteLine(newTimeZone.IsDaylightSavingTime(dateValue)); // True

var result = TimeZoneInfo.ConvertTime(dateValue, newTimeZone);
Console.WriteLine(result);

Which prints 10/06/2017 9:30:00 AM - 4 hours behind the UTC string.

Upvotes: 1

Related Questions