65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C++ 更改时区信息

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.63/5 (13投票s)

2004年6月15日

CPOL
viewsIcon

79083

downloadIcon

554

以编程方式修改 Windows 时区信息。

引言

该程序演示了如何以编程方式修改 Windows 时区信息。

背景

我在互联网上很少看到关于如何使用 C++ 以编程方式修改 Windows 时区信息的资料。本文将向您展示如何操作。

有一个可用时区列表。该列表位于注册表中,路径为 _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones")。但是,没有数据结构可以与注册表键中的现有 TZI 二进制值一起工作。

这是东部标准时间 TZI 注册表二进制数据示例

这是总字节集

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

让我们解读一下这是什么…

(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

您会注意到,它代表了 TIME_ZONE_INFO 结构。

struct TIME_ZONE_INFO // TZI
{
    ULONG Bias;
    ULONG StandardBias;
    ULONG DaylightBias;
    SYSTEMTIME StandardDate;
    SYSTEMTIME DaylightDate;
};

使用代码

下面,您将找到文本形式的源代码。

/************************************************
*
*    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;
}

历史

  • 2006 年 2 月 2 日 - 修复了关于 TimeZoneInfoToTimeZoneInformation 函数的一个重大错误。
  • 2005 年 2 月 9 日 - 清理了代码并使其更易读。
© . All rights reserved.