Ah, leftovers from DST...

Yesterday I got looped into a call where a customer that reported that meeting requests were ahead by an hour when he sent them to the Internet.  Knowing this had to have something to do with Timezones and DST, I whipped together a quick tool to Display UTC time, Local time, and some other time zone information. 

 We can always verify what's in the Windows Time Zone Database using TZEdit but not information on the current time zone.  You could also pull this from the registry HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\TimeZoneInformation if you know how to interpret the data, but this makes it much easier.  But in addition to all this, I would've never figured out this issue without the UTC display from this tool. 

In the customer's case, the UTC time showed he was an hour ahead of the rest of the world in his domain but because he had hacked up his timezone information to display the local time correctly, he had no idea his UTC time was wrong.

Here is some sample output:

UTC System Time: 9/5/2007 21:47
Local System Time: 9/5/2007 17:47
Operating in DAYLIGHT time
Time Zone Name: Eastern Daylight Time
Daylight Bias: -60 Minutes (or -1 Hours)
Standard: Occurs first Sunday of November at 2: 0
Daylight: Occurs second Sunday of March at 2: 0
Bias: 300 Minutes (or 5 Hours)

For anyone who's interested, here is the source of the main function.  It demonstrates the use of the GetSystemTime, SystemTimeToTzSpecificLocalTime, and GetTimeZoneInformation functions.

int _tmain(int argc, _TCHAR* argv[])

{

      SYSTEMTIME utctime;

     

      // Apparently this function cannot fail - no need to check error case

      GetSystemTime(&utctime);

           

      wprintf(

            L"UTC System Time: %i/%i/%i %i:%i\r\n",

            utctime.wMonth,

            utctime.wDay,

            utctime.wYear,

            utctime.wHour,

            utctime.wMinute

            );

      SYSTEMTIME localtime;

      BOOL fResult = SystemTimeToTzSpecificLocalTime(

            NULL, // current timezone

            &utctime, // input time

            &localtime // output time

            );

      if(!fResult)

      {

            wprintf(L"SystemTimeToTzSpecificLocalTime failed.\r\n");

            return -1;

      }

      wprintf(

            L"Local System Time: %i/%i/%i %i:%i\r\n",

            localtime.wMonth,

            localtime.wDay,

            localtime.wYear,

            localtime.wHour,

            localtime.wMinute

            );

      TIME_ZONE_INFORMATION tzInfo;

      DWORD dwResult = GetTimeZoneInformation(&tzInfo);

      switch(dwResult)

      {

            case 0:

                  wprintf(L"Operating in UNKNOWN time\r\n");

                  return -1;

            case 1:

                  wprintf(L"Operating in STANDARD time\r\n");

                  wprintf(L"Time Zone Name: %s \r\n", tzInfo.StandardName);

                  wprintf(L"Standard Bias: %i Minutes (or %i Hours) \r\n", tzInfo.StandardBias, tzInfo.StandardBias / 60);

                  break;

            case 2:

                  wprintf(L"Operating in DAYLIGHT time\r\n");

                  wprintf(L"Time Zone Name: %s \r\n", tzInfo.DaylightName);

                  wprintf(L"Daylight Bias: %i Minutes (or %i Hours) \r\n", tzInfo.DaylightBias, tzInfo.DaylightBias / 60);

                  break;

            default:

                  return -1;

      }

      wprintf(L"Standard: Occurs %s %s of %s at %i:%2i\r\n",

                        GetOccurrenceString(tzInfo.StandardDate.wDay),

                        GetDayString(tzInfo.StandardDate.wDayOfWeek),

                        GetMonthString(tzInfo.StandardDate.wMonth),

                        tzInfo.StandardDate.wHour,

                        tzInfo.StandardDate.wMinute

                  );

      wprintf(L"Daylight: Occurs %s %s of %s at %i:%2i\r\n",

                        GetOccurrenceString(tzInfo.DaylightDate.wDay),

                        GetDayString(tzInfo.DaylightDate.wDayOfWeek),

                        GetMonthString(tzInfo.DaylightDate.wMonth),

                        tzInfo.DaylightDate.wHour,

                        tzInfo.DaylightDate.wMinute

                  );

      wprintf(L"Bias: %i Minutes (or %i Hours) \r\n", tzInfo.Bias, tzInfo.Bias / 60);

     

      _getch();

     

      return 0;

}