Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DateTime.ToLocalTime on Windows XP

The documentation for the .NET DateTime.ToLocalTime method states:

On Windows XP systems, the ToLocalTime method recognizes only the current adjustment rule when converting from UTC to local time. As a result, conversions for periods before the current adjustment rule came into effect may not accurately reflect the difference between UTC and local time.

I'm developing on Windows 7 but deploying to a mixed environment. How can I provide a consistent, correct implementation that matches the Windows 7 behavior of ToLocalTime?

EDIT

I ran a test:

static void Main()
{
    // 8 AM in July, UTC. That would have been DST, so 3 AM CDT.
    var dstDate = new DateTime(2010, 7, 1, 8, 0, 0, DateTimeKind.Utc);

    // 8 AM in December, UTC. Not DST, so 2 AM CST.
    var nonDstDate = new DateTime(2010, 12, 1, 8, 0, 0, DateTimeKind.Utc);

    Log("DST Date ToLocalTime: " + dstDate.ToLocalTime());
    Log("DST Date ConvertTimeFromUtc: " + ConvertTimeFromUtc(dstDate));
    Log("Expected: 3 AM July 1 2010");

    Log(string.Empty);

    Log("Non-DST Date ToLocalTime: " + nonDstDate.ToLocalTime());
    Log("Non-DST Date ConvertTimeFromUtc: " + ConvertTimeFromUtc(nonDstDate));
    Log("Expected: 2 AM December 1 2010");

    Log(string.Empty);

    Log("Date ToLocalTime Kind: " + dstDate.ToLocalTime().Kind);
    Log("Date ConvertTimeFromUtc Kind: " + ConvertTimeFromUtc(dstDate).Kind);
}

private static void Log(string message)
{
    Console.WriteLine(message);
}

private static DateTime ConvertTimeFromUtc(DateTime utcDateTime)
{
    return
        DateTime.SpecifyKind(
            TimeZoneInfo.ConvertTimeFromUtc(
                utcDateTime,
                TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id)),
            DateTimeKind.Local);
}

The results were identical under XP Pro 32-bit, SP3 (as VM) and Windows 7 Enterprise 64-bit:

DST Date ToLocalTime: 7/1/2010 3:00:00 AM
DST Date ConvertTimeFromUtc: 7/1/2010 3:00:00 AM
Expected: 3 AM July 1 2010

Non-DST Date ToLocalTime: 12/1/2010 2:00:00 AM
Non-DST Date ConvertTimeFromUtc: 12/1/2010 2:00:00 AM
Expected: 2 AM December 1 2010

Date ToLocalTime Kind: Local
Date ConvertTimeFromUtc Kind: Local

Is the documentation wrong? Can I simply call ToLocalTime?

EDIT 2

We ran this on an actual XP system (not a VM) and got identical results there as well. Are my test cases correct? Can anyone provide a case where the results will differ?

like image 939
TrueWill Avatar asked Feb 10 '11 17:02

TrueWill


2 Answers

On Windows XP systems, the ToLocalTime method recognizes only the current adjustment rule when converting from UTC to local time. As a result, conversions for periods before the current adjustment rule came into effect may not accurately reflect the difference between UTC and local time.

The US changed the adjustment rule for DST in 2007.

  • 2006: Start 1st Sunday in April, End last Sunday in October.
  • 2007: Start 2nd Sunday in March, End 1st Sunday in November.

The bug is that they're following the 2007 rules for all dates, not just dates after 2007. The DST rules hadn't changed in 20 years, Windows XP just doesn't have the concept of different rules for different years. It will consider October 31, 2006 to be in Daylight Savings, when it actually wasn't.

If you're only dealing with dates after 2007, then you're good, no need to do anything special. If you're dealing with dates in or before 2006, then you'll need to check the year, and apply the DST offset manually.

like image 149
David Yaw Avatar answered Sep 23 '22 15:09

David Yaw


You can use the System.TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo, TimeZoneInfo) method to convert the time from the source's timezone to the user's local timezone.

like image 29
NoAlias Avatar answered Sep 21 '22 15:09

NoAlias