EDN Admin
Well-known member
Hi
We have found that SystemTimeToTzSpecificLocalTime(NULL, ..) and GetTimeZoneInformation() works differently over Windows 7 and Windows XP.
Here are some conditions of testing:
I live in Sydney, Australia, which uses DST at this time of year. For example, the time right now is 11.00 am (6th, March 2012) and when I turn off "Automatically adjust clock for Daylight Saving Time" on Time Zone Settings, the local time on Windows will
be 10.00 am. I installed the latest DST patch from Microsoft for Windows XP. All test codes were done via Win32 C++ Console Projects with VS2008.GetLocalTime() cant help me as I need to convert old timestampes written in UTC as well. (But GetLocalTime() worked perfectly on Windows XP though.)
I think this code should react to that "Automatically..." setting:
<pre class="prettyprint <span class="pln <span class="kwd while<span class="pun (<span class="lit 1<span class="pun ) <span class="pln <span class="pun { <span class="pln SYSTEMTIME st <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun },<span class="pln lt <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="typ GetSystemTime<span class="pun (&<span class="pln st<span class="pun );<span class="pln
<span class="typ SystemTimeToTzSpecificLocalTime<span class="pun (<span class="pln NULL<span class="pun ,<span class="pln <span class="pun &<span class="pln st<span class="pun ,<span class="pln <span class="pun &<span class="pln lt<span class="pun );<span class="pln
printf<span class="pun (<span class="str "%d %d %d, %d:%d:%dn"<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wDay<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMonth<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wYear<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wHour<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMinute<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wSecond<span class="pun );<span class="pln
<span class="pln <span class="typ Sleep<span class="pun (<span class="lit 1000<span class="pun ); <span class="pln <span class="pun } [/code]
And this worked as I expected on Windows 7; when I turned off the "Automatically.." setting, the time displayed on console and Windows clock went to 1 hr earlier, which was natural because I let Windows act as if theres no DST. (Thats my understanding
of "Automatically..." option.)
However, on Windows XP, the hour did not change as per that "Automatically.." setting but just showed me the current (real) time as if the setting was
still turned on. Eventually the displayed time was NOT same as one on Windows clock when the setting was turned off.
<br/>
As per the document of SystemTimeToTzSpecificLocalTime(), I think calling this function with NULL as the first parameter is equivalent to this code:
<pre class="prettyprint <span class="pln TIME_ZONE_INFORMATION tz <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
SYSTEMTIME st <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun },<span class="pln lt <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="typ GetSystemTime<span class="pun (&<span class="pln st<span class="pun );<span class="pln
<span class="typ GetTimeZoneInformation<span class="pun (&<span class="pln tz<span class="pun );<span class="pln
<span class="typ SystemTimeToTzSpecificLocalTime<span class="pun (&<span class="pln tz<span class="pun ,<span class="pln <span class="pun &<span class="pln st<span class="pun ,<span class="pln <span class="pun &<span class="pln lt<span class="pun );<span class="pln
printf<span class="pun (<span class="str "[2] %d %d %d, %d:%d:%dn"<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wDay<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMonth<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wYear<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wHour<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMinute<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wSecond<span class="pun );[/code]
And this code block did the exact same thing on Windows XP. Then as I was suspicious of TIME_ZONE_INFORMATION structure, I tested GetTimeZoneInformation() as well and have found something interesting. I used this code followed by its result on
Windows 7 and XP:
<pre class="prettyprint lang-vb <span class="pln Test Code <span class="kwd for<span class="pln GTZI<span class="pun :<span class="pln
TIME_ZONE_INFORMATION tzi <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="pun ::<span class="pln GetTimeZoneInformation<span class="pun (&<span class="pln tzi<span class="pun );<span class="pln
I have dumped the contents of TZI <span class="kwd on<span class="pln W7 <span class="kwd and<span class="pln WXP whilst changing the <span class="str "Automatically adjust clock for DST"<span class="pln setting <span class="kwd and<span class="pln here<span class="com s the difference: <span class="pln
Windows <span class="lit 7<span class="pln w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting <span class="kwd ON<span class="pln
<span class="pun ------------------<span class="pln
StandardName<span class="pun :<span class="pln AUS Eastern Standard Time
StandardDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 4<span class="pln <span class="lit 0<span class="pln
StandardBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
DaylightName<span class="pun :<span class="pln AUS Eastern Daylight Time
DaylightDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 10<span class="pln <span class="lit 0<span class="pln
DaylightBias<span class="pun :<span class="pln <span class="pun -<span class="lit 60<span class="pln
Windows XP w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting <span class="kwd ON<span class="pln
<span class="pun ------------------<span class="pln
<span class="pun **<span class="pln Same <span class="kwd as<span class="pln above <span class="pun **<span class="pln
Windows <span class="lit 7<span class="pln w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting OFF
<span class="pun ------------------<span class="pln
StandardName<span class="pun :<span class="pln AUS Eastern Standard Time
StandardDate<span class="pun :<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln
StandardBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
DaylightName<span class="pun :<span class="pln AUS Eastern Standard Time
DaylightDate<span class="pun :<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln
DaylightBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
Windows XP w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting OFF
<span class="pun ------------------<span class="pln
StandardName<span class="pun :<span class="pln AUS Eastern Standard Time
<span class="pun **<span class="pln StandardDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 4<span class="pln <span class="lit 0<span class="pln <span class="pun **<span class="pln
StandardBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
DaylightName<span class="pun :<span class="pln AUS Eastern Standard Time
<span class="pun **<span class="pln DaylightDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 4<span class="pln <span class="lit 0<span class="pln <span class="pun **<span class="pln
DaylightBias<span class="pun :<span class="pln <span class="lit 0[/code]
This means, at least GetTimeZoneInformation() works differently on Windows 7 and Windows XP. Actually GTZI() returns TIME_ZONE_ID_UNKNOWN on Windows 7 when that "Automatically..." setting was turned off, but this never happen on Windows XP regardless of
that setting unless the Time Zone is changed to somewhere does not use DST at all (e.g. Darwin, Seoul, Taipei, ...)
So I did some tests again to reset "StandardTime" and "DaylightTime" to zero if "StandardName" and "DaylightName" were identical to each other, (just like Windows 7 did), the issue disappeared on Windows XP as well:
<pre class="prettyprint <span class="pln <span class="pun {<span class="pln
TIME_ZONE_INFORMATION tz <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
SYSTEMTIME st <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun },<span class="pln lt <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="typ GetSystemTime<span class="pun (&<span class="pln st<span class="pun );<span class="pln
DWORD timeZoneID <span class="pun =<span class="pln <span class="typ GetTimeZoneInformation<span class="pun (&<span class="pln tz<span class="pun );<span class="pln
<span class="kwd if<span class="pln <span class="pun (<span class="lit 0<span class="pln <span class="pun ==<span class="pln wcscmp<span class="pun (<span class="pln tz<span class="pun .<span class="typ DaylightName<span class="pun ,<span class="pln tz<span class="pun .<span class="typ StandardName<span class="pun ))<span class="pln
<span class="pun {<span class="pln
memset<span class="pun (&<span class="pln tz<span class="pun .<span class="typ StandardDate<span class="pun ,<span class="pln <span class="lit 0<span class="pun ,<span class="pln <span class="kwd sizeof<span class="pun (<span class="pln SYSTEMTIME<span class="pun ));<span class="pln
memset<span class="pun (&<span class="pln tz<span class="pun .<span class="typ DaylightDate<span class="pun ,<span class="pln <span class="lit 0<span class="pun ,<span class="pln <span class="kwd sizeof<span class="pun (<span class="pln SYSTEMTIME<span class="pun ));<span class="pln
<span class="pun }<span class="pln
<span class="typ SystemTimeToTzSpecificLocalTime<span class="pun (&<span class="pln tz<span class="pun ,<span class="pln <span class="pun &<span class="pln st<span class="pun ,<span class="pln <span class="pun &<span class="pln lt<span class="pun );<span class="pln
printf<span class="pun (<span class="str "%d %d %d, %d:%d:%d (TzID: %d)n"<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wDay<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMonth<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wYear<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wHour<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMinute<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wSecond<span class="pun ,<span class="pln timeZoneID<span class="pun );<span class="pln
<span class="typ Sleep<span class="pun (<span class="lit 1000<span class="pun );<span class="pln
<span class="pun }[/code]
Here are my questions:
<ol>
Were my tests done correctly? If this behaviour (the difference between Windows 7 and XP) is by design, which document from Microsoft has that information?
Does my work around on the last source code seem okay? Or, is there any other solution for this, except of calculating local time manually?
It seemed that a breaking change was introduced about 2007 to have "Dynamic Time Zone Information" and its relevant functions on Windows but this new structure is supported by Windows Vista and later only. I would also like to know this
behaviour is related to the change. </ol>
Thanks in advance
View the full article
We have found that SystemTimeToTzSpecificLocalTime(NULL, ..) and GetTimeZoneInformation() works differently over Windows 7 and Windows XP.
Here are some conditions of testing:
I live in Sydney, Australia, which uses DST at this time of year. For example, the time right now is 11.00 am (6th, March 2012) and when I turn off "Automatically adjust clock for Daylight Saving Time" on Time Zone Settings, the local time on Windows will
be 10.00 am. I installed the latest DST patch from Microsoft for Windows XP. All test codes were done via Win32 C++ Console Projects with VS2008.GetLocalTime() cant help me as I need to convert old timestampes written in UTC as well. (But GetLocalTime() worked perfectly on Windows XP though.)
I think this code should react to that "Automatically..." setting:
<pre class="prettyprint <span class="pln <span class="kwd while<span class="pun (<span class="lit 1<span class="pun ) <span class="pln <span class="pun { <span class="pln SYSTEMTIME st <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun },<span class="pln lt <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="typ GetSystemTime<span class="pun (&<span class="pln st<span class="pun );<span class="pln
<span class="typ SystemTimeToTzSpecificLocalTime<span class="pun (<span class="pln NULL<span class="pun ,<span class="pln <span class="pun &<span class="pln st<span class="pun ,<span class="pln <span class="pun &<span class="pln lt<span class="pun );<span class="pln
printf<span class="pun (<span class="str "%d %d %d, %d:%d:%dn"<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wDay<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMonth<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wYear<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wHour<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMinute<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wSecond<span class="pun );<span class="pln
<span class="pln <span class="typ Sleep<span class="pun (<span class="lit 1000<span class="pun ); <span class="pln <span class="pun } [/code]
And this worked as I expected on Windows 7; when I turned off the "Automatically.." setting, the time displayed on console and Windows clock went to 1 hr earlier, which was natural because I let Windows act as if theres no DST. (Thats my understanding
of "Automatically..." option.)
However, on Windows XP, the hour did not change as per that "Automatically.." setting but just showed me the current (real) time as if the setting was
still turned on. Eventually the displayed time was NOT same as one on Windows clock when the setting was turned off.
<br/>
As per the document of SystemTimeToTzSpecificLocalTime(), I think calling this function with NULL as the first parameter is equivalent to this code:
<pre class="prettyprint <span class="pln TIME_ZONE_INFORMATION tz <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
SYSTEMTIME st <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun },<span class="pln lt <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="typ GetSystemTime<span class="pun (&<span class="pln st<span class="pun );<span class="pln
<span class="typ GetTimeZoneInformation<span class="pun (&<span class="pln tz<span class="pun );<span class="pln
<span class="typ SystemTimeToTzSpecificLocalTime<span class="pun (&<span class="pln tz<span class="pun ,<span class="pln <span class="pun &<span class="pln st<span class="pun ,<span class="pln <span class="pun &<span class="pln lt<span class="pun );<span class="pln
printf<span class="pun (<span class="str "[2] %d %d %d, %d:%d:%dn"<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wDay<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMonth<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wYear<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wHour<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMinute<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wSecond<span class="pun );[/code]
And this code block did the exact same thing on Windows XP. Then as I was suspicious of TIME_ZONE_INFORMATION structure, I tested GetTimeZoneInformation() as well and have found something interesting. I used this code followed by its result on
Windows 7 and XP:
<pre class="prettyprint lang-vb <span class="pln Test Code <span class="kwd for<span class="pln GTZI<span class="pun :<span class="pln
TIME_ZONE_INFORMATION tzi <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="pun ::<span class="pln GetTimeZoneInformation<span class="pun (&<span class="pln tzi<span class="pun );<span class="pln
I have dumped the contents of TZI <span class="kwd on<span class="pln W7 <span class="kwd and<span class="pln WXP whilst changing the <span class="str "Automatically adjust clock for DST"<span class="pln setting <span class="kwd and<span class="pln here<span class="com s the difference: <span class="pln
Windows <span class="lit 7<span class="pln w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting <span class="kwd ON<span class="pln
<span class="pun ------------------<span class="pln
StandardName<span class="pun :<span class="pln AUS Eastern Standard Time
StandardDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 4<span class="pln <span class="lit 0<span class="pln
StandardBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
DaylightName<span class="pun :<span class="pln AUS Eastern Daylight Time
DaylightDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 10<span class="pln <span class="lit 0<span class="pln
DaylightBias<span class="pun :<span class="pln <span class="pun -<span class="lit 60<span class="pln
Windows XP w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting <span class="kwd ON<span class="pln
<span class="pun ------------------<span class="pln
<span class="pun **<span class="pln Same <span class="kwd as<span class="pln above <span class="pun **<span class="pln
Windows <span class="lit 7<span class="pln w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting OFF
<span class="pun ------------------<span class="pln
StandardName<span class="pun :<span class="pln AUS Eastern Standard Time
StandardDate<span class="pun :<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln
StandardBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
DaylightName<span class="pun :<span class="pln AUS Eastern Standard Time
DaylightDate<span class="pun :<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln <span class="lit 0<span class="pln
DaylightBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
Windows XP w<span class="pun /<span class="pln <span class="str "Automatically..."<span class="pln Setting OFF
<span class="pun ------------------<span class="pln
StandardName<span class="pun :<span class="pln AUS Eastern Standard Time
<span class="pun **<span class="pln StandardDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 4<span class="pln <span class="lit 0<span class="pln <span class="pun **<span class="pln
StandardBias<span class="pun :<span class="pln <span class="lit 0<span class="pln
DaylightName<span class="pun :<span class="pln AUS Eastern Standard Time
<span class="pun **<span class="pln DaylightDate<span class="pun :<span class="pln <span class="lit 1<span class="pln <span class="lit 4<span class="pln <span class="lit 0<span class="pln <span class="pun **<span class="pln
DaylightBias<span class="pun :<span class="pln <span class="lit 0[/code]
This means, at least GetTimeZoneInformation() works differently on Windows 7 and Windows XP. Actually GTZI() returns TIME_ZONE_ID_UNKNOWN on Windows 7 when that "Automatically..." setting was turned off, but this never happen on Windows XP regardless of
that setting unless the Time Zone is changed to somewhere does not use DST at all (e.g. Darwin, Seoul, Taipei, ...)
So I did some tests again to reset "StandardTime" and "DaylightTime" to zero if "StandardName" and "DaylightName" were identical to each other, (just like Windows 7 did), the issue disappeared on Windows XP as well:
<pre class="prettyprint <span class="pln <span class="pun {<span class="pln
TIME_ZONE_INFORMATION tz <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
SYSTEMTIME st <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun },<span class="pln lt <span class="pun =<span class="pln <span class="pun {<span class="lit 0<span class="pun };<span class="pln
<span class="typ GetSystemTime<span class="pun (&<span class="pln st<span class="pun );<span class="pln
DWORD timeZoneID <span class="pun =<span class="pln <span class="typ GetTimeZoneInformation<span class="pun (&<span class="pln tz<span class="pun );<span class="pln
<span class="kwd if<span class="pln <span class="pun (<span class="lit 0<span class="pln <span class="pun ==<span class="pln wcscmp<span class="pun (<span class="pln tz<span class="pun .<span class="typ DaylightName<span class="pun ,<span class="pln tz<span class="pun .<span class="typ StandardName<span class="pun ))<span class="pln
<span class="pun {<span class="pln
memset<span class="pun (&<span class="pln tz<span class="pun .<span class="typ StandardDate<span class="pun ,<span class="pln <span class="lit 0<span class="pun ,<span class="pln <span class="kwd sizeof<span class="pun (<span class="pln SYSTEMTIME<span class="pun ));<span class="pln
memset<span class="pun (&<span class="pln tz<span class="pun .<span class="typ DaylightDate<span class="pun ,<span class="pln <span class="lit 0<span class="pun ,<span class="pln <span class="kwd sizeof<span class="pun (<span class="pln SYSTEMTIME<span class="pun ));<span class="pln
<span class="pun }<span class="pln
<span class="typ SystemTimeToTzSpecificLocalTime<span class="pun (&<span class="pln tz<span class="pun ,<span class="pln <span class="pun &<span class="pln st<span class="pun ,<span class="pln <span class="pun &<span class="pln lt<span class="pun );<span class="pln
printf<span class="pun (<span class="str "%d %d %d, %d:%d:%d (TzID: %d)n"<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wDay<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMonth<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wYear<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wHour<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wMinute<span class="pun ,<span class="pln lt<span class="pun .<span class="pln wSecond<span class="pun ,<span class="pln timeZoneID<span class="pun );<span class="pln
<span class="typ Sleep<span class="pun (<span class="lit 1000<span class="pun );<span class="pln
<span class="pun }[/code]
Here are my questions:
<ol>
Were my tests done correctly? If this behaviour (the difference between Windows 7 and XP) is by design, which document from Microsoft has that information?
Does my work around on the last source code seem okay? Or, is there any other solution for this, except of calculating local time manually?
It seemed that a breaking change was introduced about 2007 to have "Dynamic Time Zone Information" and its relevant functions on Windows but this new structure is supported by Windows Vista and later only. I would also like to know this
behaviour is related to the change. </ol>
Thanks in advance
View the full article