Solved

Enumerating Windows TimeZone information

Posted on 2003-11-08
6
468 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
  • 2
  • 2
  • 2
6 Comments
 
LVL 4

Expert Comment

by:SurferJoe
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
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
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:SurferJoe
ID: 9724146
Great job F68
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
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…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

760 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now