Solved

Enumerating Windows TimeZone information

Posted on 2003-11-08
6
485 Views
Last Modified: 2010-04-05
Hi experts,

I'm needing to be able to enumerate the available time zone lists so that I can use the bias details to fill a lpTimeZone structure ... and I haven't a clue how to go about it.

I suppose it is possible to walk through the different registry entries in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones and then decrypt the different binary storage values, but this seems *way* too inefficient.

I've tried searching msdn for variations of EnumTimeZones and different connotations to that effect and come up with a big fat zero.

What I am ultimately trying to do is give a user a list of time zones, as can be found in Adjust Date / Time in windows, so that they can choose a different locality to display a secondary clock that is different from their own.

For example, I'm in UK and want to have a dual clock that shows my current time alongside say current time in Tokyo, JP, and take into account daylight savings and such things.

In my investigations of how i might go about this, I've found the API call, SystemTimeToTzSpecificLocalTime, which I'm sure is the way i need to proceed to get this job done. But this function needs a fully built lpTimeZone structure to be able to pass back the alternative systemtime.

Therefore, if i can enumerate windows built in timezone structures, i can pass them in as required.

I'm guessing what I need to end up with from you people is a way to generate an array of fully built timezone structures from windows own time rules.

Another problem is that I'm not at all proficient in the use of the Win API

Any help is greatly appreciated - hence the generous points on offer

Many thanks in advance

Darren
0
Comment
Question by:elkiors
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
  • 2
6 Comments
 
LVL 4

Expert Comment

by:Greg Rowland
ID: 9707737
Win32 SDK Help file, Find zone.

I believe everything you could want is documented there.
0
 
LVL 22

Accepted Solution

by:
Ferruccio Accalai earned 500 total points
ID: 9713953
well.....Win32 SDK fil is a little bit summary.....BTW look at this example.i think you can find most of what you need in it:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,registry;

type

  TRegTZI = packed record
    Bias: Longint;
    StandardBias: Longint;
    DaylightBias: Longint;
    StandardDate: TSystemTime;
    DaylightDate: TSystemTime;
  end;
  TForm1 = class(TForm)
    Button2: TButton;
    Memo1: TMemo;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure SHowDateTime(reg: TRegistry;memoinfo: Tmemo;standardname,DaylightName:STring);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
function GetTZFromRegistry(reg: TRegistry):string;
var
  regTZI: TRegTZI;
  d: TDAteTime;
begin
  Result := '';
  if assigned(reg) then begin
    with reg do begin
        if GetDataSize('TZI') = SizeOf(regTZI) then begin
        ReadBinaryData('TZI',regTZI,SizeOf(regTZI));
        d := now + regtzi.Bias/1440;
        Result := DateTimeToSTr(d);
      end;
    end;
  end;
end; { GetTZFromRegistry}

PROCEDURE TForm1.ShowDateTime(reg: TRegistry;memoinfo: Tmemo;standardname,DaylightName:STring);
  var
  regTZI: TRegTZI;
  d: TDAteTime;
  FUNCTION DayInMonth(CONST w: WORD): STRING;
  BEGIN
    CASE w OF
      1: RESULT := '1st';
      2: RESULT := '2nd';
      3: RESULT := '3rd';
      4: RESULT := '4th';
      5: RESULT := 'Last';
      ELSE RESULT := 'Unknown'
    END
  END {DayInMonth};

BEGIN
  if assigned(reg) then begin
    with reg do begin
      if GetDataSize('TZI') = SizeOf(regTZI) then begin
        ReadBinaryData('TZI',regTZI,SizeOf(regTZI));
        with regtzi do begin
              IF   StandardDate.wYear = 0
              THEN MemoInfo.Lines.Add(' ' + StandardName + ' Starts ' +
                   DayInMonth(StandardDate.wDay) + ' ' +
                   LongDayNames[1+StandardDate.wDayofWeek] + ' of ' +
                   LongMonthNames[StandardDate.wMonth])
              ELSE MemoInfo.Lines.Add(' ' + StandardName + ' Starts ' +
                   Format('%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d',
                   [StandardDate.wMonth, StandardDate.wDay,
                   StandardDate.wYear,
                   StandardDate.wHour, StandardDate.wMinute,
                   StandardDate.wSecond]));
              IF   DaylightDate.wYear = 0
              THEN MemoInfo.Lines.Add(' ' + DaylightName + ' Starts ' +
                   DayInMonth(DaylightDate.wDay) + ' ' +
                   LongDayNames[1+DaylightDate.wDayofWeek] + ' of ' +
                   LongMonthNames[DaylightDate.wMonth])
              ELSE MemoInfo.Lines.Add(' ' + DaylightName + ' Starts ' +
                   Format('%2.2d/%2.2d/%4.4 %2.2d:%2.2d:%2.2d',
                   [DaylightDate.wMonth, DaylightDate.wDay,
                   DaylightDate.wYear,
                   DaylightDate.wHour, DaylightDate.wMinute,
                   DaylightDate.wSecond]));
         end;
      end;
  end;
  end;
END {ShowDateTime};
procedure TForm1.Button2Click(Sender: TObject);
var
  reg : TRegistry;
  ts : TStringList;
  i : integer;
begin
  reg := TRegistry.Create;
  reg.RootKey := HKEY_LOCAL_MACHINE;
  reg.OpenKey(
'SOFTWARE\Microsoft\Windows nt\CurrentVersion\Time Zones',
              false);
  if reg.HasSubKeys then begin
    ts := TStringList.Create;
    ts.sorted := True;
    reg.GetKeyNames(ts);
    reg.CloseKey;

    for i := 0 to ts.Count -1 do begin
      reg.OpenKey(
  'SOFTWARE\Microsoft\Windows nt\CurrentVersion\Time Zones\' +
        ts.Strings[i],
      false);
      Memo1.Lines.Add(ts.Strings[i]);
      Memo1.Lines.Add(reg.ReadString('Display'));
      ShowDatetime(reg, memo1,reg.ReadString('Std'),reg.ReadString('Dlt'));
      memo1.lines.add(GetTZFromRegistry(reg));
      Memo1.Lines.Add('----------------------');
      reg.CloseKey;
    end;
    ts.Free;
  end else
  reg.CloseKey;
  reg.free;
end;

end.

F68 ;-)
0
 

Author Comment

by:elkiors
ID: 9717917
Thanks Ferruccio68 that's pretty much all that I needed, it seems there isn't a standard enumeration function in the api afterall - at least now i know i'm not going mad.

However, I did notice that your code brings up quite a few "Unknown Day of Dec" entries - does this imply that there is something wrong with the parsing of the reg data or does this indicate that the particular timezone doesn't employ any daylight saving rules ? It's confusing for me.

My fault, not yours ;)

If you can clear just that one little quirk up for me so that I can begin to understand your code and my options for manipulating the reg data then the points are yours ;)

thanks in advance

Darren
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 9720391
Well, in fact there's not a direct enumeration...btw you can check the tzi infos for the assigned tzi using windows.GetTimeZoneInformation.

About that 'Unknowns' note that the DayLight system is not applied in all Countries in the World, so it means that in that zone there's not a DayLight value (not time changes during the Year)...

For more code example you can also look here

http://17slon.com/gp/gp/files/gptimezone.htm

F68 ;-)
0
 

Author Comment

by:elkiors
ID: 9724128
Thanx F68,

that clears things up for me nicely.

I now have more than enough info to be able to work through it all a bit more and get to grips with.

Thanks again.

Darren
0
 
LVL 4

Expert Comment

by:Greg Rowland
ID: 9724146
Great job F68
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question