Solved

Enumerating Windows TimeZone information

Posted on 2003-11-08
6
480 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 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
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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.

 
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: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering 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

Title # Comments Views Activity
delphi exception 7 68
Breakpoint doesn't stop in my variable 3 30
Slow Restore if incremental backups using RDiff.exe 4 31
How to make Sign in, using Clientdataset? 1 28
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

828 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