Article View: borland.public.cppbuilder.nativeapi
Article #1796Re: TDateTime & GMT
From: Dennis Jones
Date: Wed, 20 Jun 2007 00:10
Date: Wed, 20 Jun 2007 00:10
174 lines
6362 bytes
6362 bytes
"Robert G. Hoover" <not.a.real.address@anywhere.sorry> wrote in message
news:46781ca0@newsgroups.borland.com...
> Hi All,
>
> Is there an easy way to convert the current time to a different
> timezone? Something like this...?
>
> AnsiString TimeString = Now().FormatString(GMT);
Unfortunately, no.
> Or do I have to use a TIME_ZONE_INFORMATION object or something?
Yeah, or something. I was looking at this a couple of years ago, and I
thought if you just knew the offset, you could get whatever you wanted. But
it turns out that each time zone has its own way of handling
standard/daylight time, so just knowing the timezone's offset isn't enough
to get an accurate conversion -- you also have to know its rules for
handling standard/daylight time.
So, what you have to do is:
1) Get the timezone information from the registry for both the source and
target timezones.
Note: The timezone information is in: HKLM\Software\Microsoft\Windows
NT\Time Zones\CurrentVersion. For an explanation of the format of the time
zone information in the registry, see:
http://support.microsoft.com/kb/115231
2) Convert the time from the source time zone to UTC (see:
TzSpecificLocalTimeToSystemTime).
3) Convert from UTC to the time in the target timezone (see:
SystemTimeToTzSpecificLocalTime).
If you can guarantee that your code will run on XP or higher, you can use
TzSpecificLocalTimeToSystemTime. If not, you'll have to roll your own or
get one from somewhere else. A good place to find source code for this kind
of thing is the Wine project. You will find an implementation for
TzSpecificLocalTimeToSystemTime in wine\dlls\kernel32\time.c.
Here's a quick and dirty implementation of GetTimeZoneInfoFromRegistry:
struct TZI
{
int Bias;
int StandardBias;
int DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
};
bool GetTimeZoneInfoFromRegistry(TIME_ZONE_INFORMATION &tzinfo, const
AnsiString &TZName)
{
static TIME_ZONE_INFORMATION _tzinfo;
tzinfo = _tzinfo;
bool bResult = false;
boost::scoped_ptr<TRegistry> pRegistry( new TRegistry );
pRegistry->RootKey = HKEY_LOCAL_MACHINE;
AnsiString TimeZonesKey = "Software\\Microsoft\\Windows
NT\\CurrentVersion\\Time Zones";
if ( pRegistry->OpenKey( TimeZonesKey, false ) )
{
boost::scoped_ptr<TStringList> pZones( new TStringList );
pRegistry->GetKeyNames( pZones.get() );
pRegistry->CloseKey();
int Index = pZones->IndexOf( TZName );
if ( Index != -1 )
{
AnsiString KeyToOpen = TimeZonesKey + "\\" + pZones->Strings[Index];
if ( pRegistry->OpenKey( KeyToOpen, false ) )
{
if ( pRegistry->ValueExists( "TZI" ) )
{
TZI tzi = { 0 };
if ( pRegistry->ReadBinaryData( "TZI", &tzi, sizeof(tzi) ) )
{
if ( pRegistry->ValueExists( "Std" ) )
{
AnsiString StandardName = pRegistry->ReadString( "Std" );
StandardName.WideChar( tzinfo.StandardName,
sizeof(tzinfo.StandardName) );
if ( pRegistry->ValueExists( "Dlt" ) )
{
AnsiString DaylightName = pRegistry->ReadString( "Dlt" );
DaylightName.WideChar( tzinfo.DaylightName,
sizeof(tzinfo.DaylightName) );
tzinfo.Bias = tzi.Bias;
tzinfo.StandardBias = tzi.StandardBias;
tzinfo.DaylightBias = tzi.DaylightBias;
tzinfo.StandardDate = tzi.StandardDate;
tzinfo.DaylightDate = tzi.DaylightDate;
bResult = true;
}
}
}
}
pRegistry->CloseKey();
}
}
}
return bResult;
}
Then, with some helper functions, conversion from one timezone to another is
fairly straightforward:
static void DateTimeToFileTime( const TDateTime &dt, FILETIME *ft )
{
SYSTEMTIME st;
DateTimeToSystemTime( dt, st );
SystemTimeToFileTime( &st, ft );
}
static void FileTimeToDateTime( const FILETIME *ft, TDateTime &dt )
{
SYSTEMTIME st;
FileTimeToSystemTime( ft, &st );
dt = SystemTimeToDateTime( st );
}
bool ConvertTimeZone( TDateTime &DateTime, const AnsiString &source_tz,
const AnsiString &target_tz )
{
TIME_ZONE_INFORMATION source_tzinfo;
if ( !GetTimeZoneInfoFromRegistry( source_tzinfo, source_tz ) ) return
false;
TIME_ZONE_INFORMATION target_tzinfo;
if ( !GetTimeZoneInfoFromRegistry( target_tzinfo, target_tz ) ) return
false;
FILETIME FileTime;
DateTimeToFileTime( DateTime, &FileTime );
SYSTEMTIME SystemTime;
FileTimeToSystemTime( &FileTime, &SystemTime );
SYSTEMTIME UniversalTime;
if ( !TzSpecificLocalTimeToSystemTime( &source_tzinfo, &SystemTime,
&UniversalTime ) ) return false;
if ( !SystemTimeToTzSpecificLocalTime( &target_tzinfo, &UniversalTime,
&SystemTime ) ) return false;
DateTime = SystemTimeToDateTime( SystemTime );
return true;
}
#pragma argsused
int main(int argc, char* argv[])
{
TDateTime now = Now();
printf( "The current time in Portland, Oregon is: %s\n",
now.FormatString( "hh:nn:ss" ).c_str() );
// get the current time in Bangalore, India
ConvertTimeZone( now, "Pacific Standard Time", "India Standard Time" );
printf( "The current time in Bangalore, India is: %s\n",
now.FormatString( "hh:nn:ss" ).c_str() );
return 0;
}
HTH,
- Dennis
Technical Details
Message-ID:
<46787087$1@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news.glorb.com!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mailReferences:
<46781ca0@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,92eb08d929c9d2d7 X-Google-Attributes: gid10cc67,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit From: "Dennis Jones" <nospam@nospam.com> Newsgroups: borland.public.cppbuilder.nativeapi References: <46781ca0@newsgroups.borland.com> Subject: Re: TDateTime & GMT Date: Tue, 19 Jun 2007 17:10:48 -0700 Lines: 176 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.3138 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3138 X-RFC2646: Format=Flowed; Original NNTP-Posting-Host: 71.245.109.58 Message-ID: <46787087$1@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1182298247 71.245.109.58 (19 Jun 2007 17:10:47 -0700) Path: arc1-ca.pugleaf.net!g2news1.google.com!news2.google.com!news.glorb.com!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail