c00000fd
c00000fd

Reputation: 22307

How to change system time zone in Windows?

I'm writing a software that allows to change the current time zone parameters used in Windows:

enter image description here

So far the only reference to setting a system-wide time zone that I found is the SetTimeZoneInformation API (or its variation SetDynamicTimeZoneInformation.) But I'm not really sure how I can use it to change the current time zone?

For instance, it takes TIME_ZONE_INFORMATION struct with all kinds of information about local time offset, daylight saving settings, etc. I don't understand why do I need to fill all of this info out when all I want to do is, say change the current time zone from "(UTC-08:00) Pacific Time (US & Canada)" to "(UTC-07:00) Mountain Time (US & Canada)".

Am I looking at the correct API to do that?

Upvotes: 2

Views: 2160

Answers (2)

c00000fd
c00000fd

Reputation: 22307

It's been a while, so let me try to recap what I ended up doing. Unfortunately my solution was OS specific:

  • For Windows Vista & later:

    1. Set SE_TIME_ZONE_NAME privilege.

    2. Call SetDynamicTimeZoneInformation by specifying the details of the time zone to set.

    3. Remove SE_TIME_ZONE_NAME privilege.

  • For Windows XP:

    1. Set SE_SYSTEMTIME_NAME privilege.

    2. Call SetTimeZoneInformation with information about the time zone to set.

    3. Reset SE_SYSTEMTIME_NAME privilege back.

Lastly for both OS, broadcast the following message to let running applications know that the time zone has changed:

::SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"intl",
        SMTO_ABORTIFHUNG, 
        2 * 1000,   //the total wait time can be up to the value of uTimeout multiplied by the number of top-level windows.
        NULL);

PS. To get the information on the current time zone use GetDynamicTimeZoneInformation or GetTimeZoneInformation for WinXP.

Additionally you may want to retrieve the list of all available timezones that you may use to choose the info for the new (default) timezone. You can get it from enumerating/parsing the following registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones

Check here and here for the information on its structure.

Upvotes: 1

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241808

Honestly, the easiest way is to just use the tzutil.exe utility. If you need to do this in Win32 C++, then just call from ShellExecute. Pass the ID of the time zone, not the display name.

See also my answer for doing this from .NET.

Upvotes: 0

Related Questions