🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
5 messages
5 total messages Started by Robert G. Hoover Tue, 19 Jun 2007 18:10
TDateTime & GMT
#1790
Author: Robert G. Hoover
Date: Tue, 19 Jun 2007 18:10
12 lines
1140 bytes
Hi All,

Is there an easy way to convert the current time to a different
timezone? Something like this...?

AnsiString TimeString = Now().FormatString(GMT);

Or do I have to use a TIME_ZONE_INFORMATION object or something?

Thanks!

Rob
Re: TDateTime & GMT
#1792
Author: Bob Gonder
Date: Tue, 19 Jun 2007 21:10
12 lines
1315 bytes
Robert G. Hoover wrote:

>Is there an easy way to convert the current time to a different
>timezone? Something like this...?
>
>AnsiString TimeString = Now().FormatString(GMT);

I don't think so.

>Or do I have to use a TIME_ZONE_INFORMATION object or something?

I think  SystemTimeToTzSpecificLocalTime()
Re: TDateTime & GMT
#1796
Author: Dennis Jones
Date: Wed, 20 Jun 2007 00:10
174 lines
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 
Re: TDateTime & GMT
#1701
Author: Robert G. Hoover
Date: Wed, 20 Jun 2007 20:01
4 lines
1192 bytes
Wow! Outstanding! I'm going to have to set aside some time to work
through this. Thanks so much!

Rob
Re: TDateTime & GMT
#1702
Author: Dennis Jones
Date: Wed, 20 Jun 2007 20:18
12 lines
1499 bytes
"Robert G. Hoover" <not.a.real.address@anywhere.sorry> wrote in message 
news:46798807@newsgroups.borland.com...
> Wow! Outstanding! I'm going to have to set aside some time to work
> through this. Thanks so much!

You're very welcome.  Don't assume the code is perfect though, or as if it 
has been fully tested-- it hasn't.  I threw it together rather quickly and 
just ran a few tests on it.  Though it does appear to give correct results, 
I wouldn't trust it without more testing.

- Dennis 
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads