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:47Local System Time: 9/5/2007 17:47Operating in DAYLIGHT timeTime Zone Name: Eastern Daylight TimeDaylight Bias: -60 Minutes (or -1 Hours)Standard: Occurs first Sunday of November at 2: 0Daylight: Occurs second Sunday of March at 2: 0Bias: 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;
}
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");
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);
default:
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;