Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Enumerating Windows TimeZone information

Posted on 2003-11-08
6
Medium Priority
?
505 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:Greg Rowland
ID: 9707737
Win32 SDK Help file, Find zone.

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

Accepted Solution

by:
Ferruccio Accalai earned 2000 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
Technology Partners: 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 23

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

Independent Software Vendors: 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!

Question has a verified solution.

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

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

783 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