Search code examples
c#datetimeutc

TimeZoneInfo.ConvertTimeFromUTC produce different output then TimeZone.BaseUTCOffset


I have a UTC date-time, I need to convert it to EST time zone. It should be as simple as this

 var easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
 var dt = DateTime.SpecifyKind(value, DateTimeKind.Utc);            
 return TimeZoneInfo.ConvertTimeFromUtc(dt, easternZone);

So my input date is

02-08-2019 22:53:32

and the result value is

02-08-2019 18:53:32

It deduct 4 hours from given time.

But if I check the Offset between Eastern Standard Time Zone and UTC time zone then the value it return is

easternZone.BaseUtcOffset {-05:00:00} System.TimeSpan

If this is true then above result value should be

02-08-2019 17:53:32

I am not sure what I am missing here.


Solution

  • I am not sure what I am missing here.

    BaseUtcOffset does not take into account daylight saving time (it can't, since it doesn't know what specific date you are interested in). You likely want to use GetUtcOffset:

    The returned time span includes any differences due to the application of adjustment rules to the current time zone. It differs from the BaseUtcOffset property, which returns the difference between Coordinated Universal Time (UTC) and the time zone's standard time and, therefore, does not take adjustment rules into account.

    Adjustment Rule is discussed here (emphasis mine):

    Provides information about a time zone adjustment, such as the transition to and from daylight saving time.

    As a general rule, if dates are ever <= 1 hour out from what you expect, look into daylight savings issues.

    To illustrate the impact of daylight saving time:

    var timeUtc = Convert.ToDateTime("01-01-2019 22:53:32");
    var easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    var dt = DateTime.SpecifyKind(timeUtc, DateTimeKind.Utc);            
    Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(dt, easternZone));
    Console.WriteLine(easternZone.GetUtcOffset(dt));
    
    timeUtc = Convert.ToDateTime("07-07-2019 22:53:32");
    easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    dt = DateTime.SpecifyKind(timeUtc, DateTimeKind.Utc);            
    Console.WriteLine(TimeZoneInfo.ConvertTimeFromUtc(dt, easternZone));
    Console.WriteLine(easternZone.GetUtcOffset(dt));
    

    The above code will output:

    1/1/2019 5:53:32 PM
    -05:00:00
    7/7/2019 6:53:32 PM
    -04:00:00