Click here to Skip to main content
15,887,446 members
Articles / Programming Languages / C++
Article

Changing Time Zone Information with C++

Rate me:
Please Sign up or sign in to vote.
2.63/5 (13 votes)
6 Feb 2006CPOL 77.8K   535   23   9
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralTime zone to another time zone Pin
BWM200231-Aug-07 3:43
BWM200231-Aug-07 3:43 
GeneralPartial work on my PC Pin
MFC23-Aug-06 4:41
MFC23-Aug-06 4:41 
GeneralRe: Partial work on my PC Pin
Ludvik Jerabek26-Aug-06 5:57
Ludvik Jerabek26-Aug-06 5:57 
Generalchanging time zones Pin
pzwag13-Feb-06 12:42
pzwag13-Feb-06 12:42 
GeneralRe: changing time zones Pin
Ludvik Jerabek13-Feb-06 16:49
Ludvik Jerabek13-Feb-06 16:49 
Yes this may be possible to do, though I have never actually done it myself.

Notice at the top of the article I explain what the different registry data represents:

2C 01 00 00 = 00 00 01 2C = 300 (minutes) Bias
00 00 00 00 = 00 00 00 00 = 0 (minutes) StdBias
C4 FF FF FF = FF FF FF C4 = 4294967236 = (-60 minutes) DltBias

Localtime = UTC(Coordinated Universal Time) - ( Bias + ( Dlt Bias or Std Bias ) )

or

Localtime = UTC - ( Bias + (Savings) ) where savings is set to either DLT or STD

For example it is 0:00 UTC(Coordinated Universal Time) :
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(Eastern Daylight Time)(Fall)

BIAS 5:00 Hrs or ( 300 minutes ) in relation to UTC
DLTB -1:00 Hrs or ( -60 Minutes ) in daylight time bias
_________________________________________
UTC 0:00 ( UTC )
- BIAS 4:00 ( BIAS + (DLTB))
_________________________________________
8:00 PM EDT

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(Eastern Standard Time)(Spring)
BIAS 5:00 Hrs or ( 300 minutes )
STDB 0:00 Hrs or ( 0 Minutes )
_________________________________________
UTC 0:00 ( UTC )
- BIAS 5:00 ( BIAS + (STDB) )
_________________________________________
7:00 PM STD

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Notice in some situation you will have negative biases in this case you need to take in to account the double negative. For example if you are trying to calcuate time in Islamabad this is how the equation works out.

(Islamabad Daylight Time)
BIAS -5:00 Hrs or ( -300 minutes )
DLTB -1:00 Hrs or ( -60 Minutes )
_________________________________________
UTC 0:00 ( UTC )
- BIAS 5:00 ( BIAS + (DLTB) )
_________________________________________

LocalTime = 0:00 - ( -300 +(-60) )
LocalTime = 0:00 - ( -360 )
LocalTime = 0:00 + 360
LocalTime = 6:00 AM

If you would like to change when Daylight Savings or Standard Time occurs. Change the date values for the following two SYSTEMTIME structures:

StandardDate
DaylightDate

( 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

I hope this information will help you!

Sincerely,

Ludvik Jerabek

-- modified at 11:48 Tuesday 14th February, 2006
GeneralI can't believe that it compiles Pin
ReorX2-Feb-06 2:50
ReorX2-Feb-06 2:50 
GeneralRe: I can't believe that it compiles Pin
Ludvik Jerabek2-Feb-06 7:26
Ludvik Jerabek2-Feb-06 7:26 
GeneralRe: I can't believe that it compiles Pin
Rick York2-Feb-06 7:51
mveRick York2-Feb-06 7:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.