Changing Time Zone Information with C++






2.63/5 (13 votes)
Programmatically changing the Windows time zone information.
Introduction
This program demonstrates how to change the Windows time zone information programmatically.
Background
I have seen very little information on the internet on how to change the Windows time zone information programmatically with C++. This article will show you how.
There is a list of all the time zones that are available. This is available in the registry, under _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"). However, there is no data structure that works with the existing TZI binary value in the reg key.
Here is the Eastern Standard Time TZI Reg Binary Data IE:
Here is the total set of bytes:
2C 01 00 00 00 00 00 00
C4 FF FF FF 00 00 0A 00
00 00 05 00 02 00 00 00
00 00 00 00 00 00 04 00
00 00 01 00 02 00 00 00
00 00 00 00
Let's decipher what this is...
(little-endian) => (big-endian)
2C 01 00 00 => 00 00 01 2C = 300 Bias
00 00 00 00 => 00 00 00 00 = 0 Std Bias
C4 FF FF FF => FF FF FF C4 = 4294967236 Dlt Bias
( SYSTEM TIME ) StandardDate
00 00 => 00 00 = Year
0A 00 => 00 0A = Month
00 00 => 00 00 = Day of Week
05 00 => 00 05 = Day
02 00 => 00 02 = Hour
00 00 => 00 00 = Minutes
00 00 => 00 00 = Seconds
00 00 => 00 00 = Milliseconds
( SYSTEM TIME ) DaylightDate
00 00 => 00 00 = Year
04 00 => 00 04 = Month
00 00 => 00 00 = Day of Week
01 00 => 00 01 = Day
02 00 => 00 02 = Hour
00 00 => 00 00 = Minutes
00 00 => 00 00 = Seconds
00 00 => 00 00 = Milliseconds
If you notice, it represents the TIME_ZONE_INFO
structure.
struct TIME_ZONE_INFO // TZI { ULONG Bias; ULONG StandardBias; ULONG DaylightBias; SYSTEMTIME StandardDate; SYSTEMTIME DaylightDate; };
Using the code
Below, you will find the source in text form.
/************************************************ * * Programmer: Ludvik Jerabek * Date: Feb 9, 2005 * ************************************************* #include "stdafx.h" #define TIME_REG _T("SOFTWARE\\Microsoft\\") _T("Windows NT\\CurrentVersion\\Time Zones") using namespace std; struct TIME_ZONE_INFO { ULONG Bias; ULONG StandardBias; ULONG DaylightBias; SYSTEMTIME StandardDate; SYSTEMTIME DaylightDate; }; void TimeZoneInfoToTimeZoneInformation( TIME_ZONE_INFORMATION& TimeZoneInfo1 , const TIME_ZONE_INFO& TimeZoneInfo2 ) { TimeZoneInfo1.Bias = TimeZoneInfo2.Bias ; TimeZoneInfo1.DaylightBias = TimeZoneInfo2.DaylightBias ; TimeZoneInfo1.DaylightDate = TimeZoneInfo2.DaylightDate ; TimeZoneInfo1.StandardBias = TimeZoneInfo2.StandardBias ; TimeZoneInfo1.StandardDate = TimeZoneInfo2.StandardDate ; } int _tmain(int argc, _TCHAR* argv[]) { HKEY hkTimeZones; int iErr = 1; bool bShow = false; INT dwIndexToFind = -1; for( int idx = 1 ; idx < argc && !bShow; idx++ ) { bShow = ( _tcsicmp( _T("-show") , argv[idx] ) == 0 ); } for( int idx = 1 ; idx < argc ; idx++ ) { if( _tcsicmp( _T("-index") , argv[idx] ) == 0 ) if( idx + 1 <= argc ) dwIndexToFind = _ttoi( argv[++idx] ); } if( ( bShow && dwIndexToFind == -1 ) || ( dwIndexToFind != -1 && !bShow ) ) { if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,TIME_REG,0, KEY_READ,&hkTimeZones) == ERROR_SUCCESS ) { DWORD dwIndex = 0; TCHAR tcKeyName[512]; DWORD dwcbName = 512 * sizeof( TCHAR ); FILETIME ftLastWrite; while( RegEnumKeyEx(hkTimeZones,dwIndex++,tcKeyName, &dwcbName,NULL,NULL,NULL,&ftLastWrite) != ERROR_NO_MORE_ITEMS ) { HKEY hkTimeZone; if( RegOpenKeyEx(hkTimeZones,tcKeyName,0, KEY_READ,&hkTimeZone) == ERROR_SUCCESS ) { DWORD dwTimeZoneIndex; TIME_ZONE_INFO TZI; TIME_ZONE_INFORMATION TZI2; // Get Index DWORD dwDataSize = sizeof( DWORD ); RegQueryValueEx(hkTimeZone,_T("Index"),NULL, NULL,(BYTE*)&dwTimeZoneIndex,&dwDataSize); // Get TZI Upper Bytes dwDataSize = sizeof( TIME_ZONE_INFO ); RegQueryValueEx(hkTimeZone,_T("TZI"),NULL, NULL,(BYTE*)&TZI,&dwDataSize); TimeZoneInfoToTimeZoneInformation( TZI2 , TZI ); // Get Text Values dwDataSize = 32 * sizeof( TCHAR ); RegQueryValueEx(hkTimeZone,_T("Dlt"),NULL,NULL, (BYTE*)TZI2.DaylightName,&dwDataSize); dwDataSize = 32 * sizeof( TCHAR ); RegQueryValueEx(hkTimeZone,_T("Std"),NULL,NULL, (BYTE*)TZI2.StandardName,&dwDataSize); if( bShow ) { _tprintf( _T("Index: %d\n") , dwTimeZoneIndex ); _tprintf( _T(" STD: %s\n") , TZI2.StandardName ); _tprintf( _T(" DLT: %s\n\n") , TZI2.DaylightName ); } else { if( dwTimeZoneIndex == dwIndexToFind ) if( SetTimeZoneInformation( &TZI2 ) ) iErr = 0; } RegCloseKey( hkTimeZone ); } dwcbName = 512 * sizeof( TCHAR ); } RegCloseKey( hkTimeZones ); } } else { _tprintf(_T("\nUsage:\n\n")); _tprintf(_T("tz.exe -show\n")); _tprintf(_T("tz.exe -index [get index number") _T(" from -show command for your time zone]\n")); _tprintf(_T("\n\n\nLudvik Jerabek, 2005\n")); } return iErr; }
History
- Feb 2, 2006 - Fixed a major typo with regards to the
TimeZoneInfoToTimeZoneInformation
function. - Feb 9, 2005 - Cleaned up the code and made it more readable.