IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Maîtrisez le temps avec Delphi


précédentsommairesuivant

IV. Manipulation des dates et heures du système avec Delphi

IV-A. Lecture des informations liées aux fuseaux horaires

Sous Windows, nous pouvons lire deux types d'informations liées aux fuseaux horaires (voir le chapitre précédent) :

  • les informations concernant tous les fuseaux horaires connus de Windows ;
  • les informations concernant le fuseau horaire local.

La plupart des clés de registre sont de type RG_SZ (chaînes de caractères) ou RG_DWORD (nombres) et sont facilement lisibles au moyen de la classe TRegistry.

Un problème se pose pour la lecture de la valeur de la clé « TZI » qui est de type RG_BINARY (valeur binaire).
Aussi, Delphi a prévu une classe permettant de lire et manipuler ces informations : le type TTimeZoneInformation.

Avant de se creuser les méninges dans le développement d'une application de lecture des informations des fuseaux horaires, nous allons étudier ce type.

IV-A-1. Le type « TTimeZoneInformation »

TTimeZoneInformation est un type record, défini dans l'unité Windows.pas de Delphi.
Ce type permet d'accéder aux informations spécifiques à chaque fuseau horaire.

En voici la structure :

 
Sélectionnez
type
  PTimeZoneInformation = ^TTimeZoneInformation;
  _TIME_ZONE_INFORMATION = record
    Bias: Longint;
    StandardName: array[0..31] of WCHAR;
    StandardDate: TSystemTime;
    StandardBias: Longint;
    DaylightName: array[0..31] of WCHAR;
    DaylightDate: TSystemTime;
    DaylightBias: Longint;
  end;
  {$EXTERNALSYM _TIME_ZONE_INFORMATION}
  TTimeZoneInformation = _TIME_ZONE_INFORMATION;
  TIME_ZONE_INFORMATION = _TIME_ZONE_INFORMATION;
  {$EXTERNALSYM TIME_ZONE_INFORMATION}

Étudions les champs disponibles dans un enregistrement de type TtimeZoneInformation.

  • Bias
    Ce champ, de type LongInt (Entier 32 bits signé), contient la valeur en minutes du décalage horaire appliqué actuellement.
    La valeur de Bias est la différence, en minutes, entre l'heure UTC et l'heure locale.
  • StandardName
    Ce champ, de type WideChar (Caractère standard Unicode 16 bits), contient le nom à afficher hors de la période d'heure d'été.
  • StandardDate
    Ce champ, de type record TSystemTime, contient plusieurs informations dont le jour, le mois, l'ordre du jour dans le mois, l'heure de passage à la période d'heure normale (« Passage à l'heure d'hiver »).
  • StandardBias
    Ce champ, de type LongInt (Entier 32 bits signé), contient la valeur en minutes du décalage horaire à appliquer hors période d'heure d'été.
    La valeur de StandardBias est ajoutée à la valeur de Bias hors de la période d'heure d'été.
    Pour de nombreux fuseaux horaires, StandardBias renvoie la valeur « 0 ».
  • DaylightName
    Ce champ, de type WideChar (Caractère standard Unicode 16 bits), contient le nom à afficher durant la période d'heure d'été.
    Pour les pays n'utilisant pas le système heure d'été/heure d'hiver, ce champ n'est pas renseigné.
  • DaylightDate
    Ce champ, de type record TSystemTime, contient plusieurs informations dont le jour, le mois, l'ordre du jour dans le mois, l'heure de passage à la période d'heure d'été.
  • DaylightBias
    Ce champ, de type LongInt (Entier 32 bits signé), contient la valeur en minutes du décalage horaire à appliquer durant la période d'heure d'été.
    La valeur de DaylightBias est ajoutée à la valeur de Bias durant la période d'heure d'été.
    Cette valeur est ignorée si le champ DaylightDate n'est pas renseigné.

En route pour le fabuleux monde de Delphi…

IV-A-2. Objectif du projet « Time Zones Reader »

Qu'est-ce que « Time Zones Reader » ? C'est le nom arbitraire que j'ai donné au petit logiciel que nous allons développer. ;-)

Comme son nom l'indique, il s'agira de développer un lecteur des informations de fuseaux horaires.
Il est vrai qu'il est possible d'en créer des nouveaux et de modifier les existants, mais je ne veux pas être tenu responsable de mauvaises manipulations et de suppressions de fuseaux horaires.
Je vous laisse donc le privilège de développer la partie gérant les ajouts, modifications et suppressions de fuseaux horaires…

Voici, représenté schématiquement, ce que notre logiciel va devoir être capable de faire :

Représentation schématique des fonctionnalités du logiciel

Son interface sera très simple, vous pouvez la voir ci-après, en lecture de la clé concernant le fuseau horaire de Paris :

Aperçu de l'interface finale du logiciel

Afin d'obtenir ce magnifique résultat, nous allons devoir créer une nouvelle classe qui nous permettra d'accéder à toutes ces informations. Ce sera la partie du développement la plus complexe, le reste étant de la création d'interfaces et de l'affichage d'informations.

Vous pouvez, d'ores et déjà, télécharger les sources de ce petit programme. Cela vous permettra de suivre le tutoriel plus aisément :

Télécharger les source de Time Zone Reader

Allez ! Au boulot ! Attaquons la création de la nouvelle classe… :-))

IV-A-3. L'unité « uWinTimeZone.pas »

Afin de pouvoir récupérer, stocker et manipuler toutes ces informations, nous allons créer une nouvelle classe que nous nommerons « TWinTimeZone » dans laquelle nous trouverons des items de type « TWinTimeZoneItem » :

Schéma UML

Comme vous pouvez le voir sur le schéma ci-dessus, TWinTimeZoneItem hérite de TObject.
Nous allons lui définir des propriétés qui lui seront propres. Pour notre logiciel, nous avons besoin des propriétés suivantes :

  • DisplayValue: String
    Valeur de la clé « Display » dans le registre de Windows.
  • KeyNameValue: String
    Nom de la clé propre au fuseau horaire en cours dans le registre de Windows.
  • IndexValue: Integer
    Valeur de la clé « Index » dans le registre de Windows.
  • NextStandardDate: String
    Valeur de la date de passage à l'heure standard (Heure d'hiver)
  • NextDaylightDate: String
    Valeur de la date de passage à l'heure d'été.
  • TZIValue: TTimeZoneInformation
    Valeur de la clé « TZI » dans le registre de Windows.

Quant au type TWinTimeZone, qui hérite de TObjectList, nous allons lui définir une seule et unique propriété qui nous permettra d'accéder aux valeurs récupérées :

  • Items[Index: Integer]: TWinTimeZoneItem
    Valeur d'un item de type TWinTimeZoneItem, défini par son index.

Cependant, nous allons lui ajouter différentes méthodes qui permettront de manipuler les Items :

  • function GetItem(Index: integer): TWinTimeZoneItem;
    Cette fonction permettra d'accéder à un item de TWinTimeZone via son index.
  • procedure AddItem(WinTimeZoneItem: TWinTimeZoneItem); overload;
    procedure AddItem(TzDisplay: string; TzKeyName: string; TzIndex: integer; TzTZI: TTimeZoneInformation); overload;
    Ces deux déclarations de la même procédure permettront d'ajouter des items à TWinTimeZone.
  • procedure Initialize;
    Cette procédure sera chargée de lire la base de registre et d'alimenter TWinTimeZone.
  • function Count: integer;
    Cette fonction renverra au développeur, le nombre d'éléments contenus dans TWinTimeZone, en l'occurrence ce sera le nombre de fuseaux horaires trouvés dans le registre de Windows.
  • procedure Clear;
    Cette procédure servira à nettoyer notre objet TWinTimeZone.
  • procedure SortDisplayByIndex;
    Cette procédure permettra au développeur de classer les valeurs de « Display » en fonction des valeurs de « Index » contenues dans le registre de Windows, c'est-à-dire de classer les fuseaux horaires de (GMT+13:00) à (GMT-12:00).

Je vous invite à lancer Delphi pour regarder plus en détail ces procédures, fonctions et propriétés succinctement décrites ci-dessus.

Lançons-nous maintenant dans la création du logiciel final…

IV-A-4. L'interface finale

Voici enfin le moment de tester notre unité…
Afin que vous puissiez comprendre les portions de code que je vais vous expliquer, regardez la composition de la fiche principale nommée 'fMain' :

Aperçu de la fiche frmMain

La première manipulation à effectuer est d'ajouter l'unité uWinTimeZone.pas dans la section uses de frmMain :

 
Sélectionnez
unit fMain;
interface
uses
  Windows, ..., uWinTimeZone;

Afin d'afficher les informations concernant le décalage horaire actuel sur le poste « client », nous allons implémenter le Create de frmMain de la manière suivante :

 
Sélectionnez
procedure TfrmMain.FormCreate(Sender: TObject);
var (...)
    tziCurrent: TTimeZoneInformation;
begin
  // Affichage de la date et l'heure actuelle
  lblLocalDateValue.Caption := DateTimeToStr(Now);
  // Affichage des informations de décalage horaire actuel
  case GetTimeZoneInformation(tziCurrent) of
    TIME_ZONE_ID_STANDARD:
    begin
      lblLocalNameValue.Caption := tziCurrent.StandardName;
      lblLocalBiasValue.Caption := TimeZoneBiasToStr(tziCurrent.Bias + tziCurrent.StandardBias);
    end;
    TIME_ZONE_ID_DAYLIGHT:
    begin
      lblLocalNameValue.Caption := tziCurrent.DaylightName;
      lblLocalBiasValue.Caption := TimeZoneBiasToStr(tziCurrent.Bias + tziCurrent.DaylightBias);
    end;
  end;
  (...)
end;

Ces informations étant affichées, un Timer, tmrMain (TTimer) sera chargé de mettre à jour la date et l'heure actuelle.

Il faut maintenant remplir la liste déroulante lstFuseaux (TListBox) et afficher les informations correspondantes au fuseau horaire sélectionné dans la liste.
Pour cela, il suffit de créer et d'instancier un objet de type TWinTimeZone, puis de faire appel à ses méthodes…
Les sources du programme étant commentées, je vous laisse le soin d'étudier le code spécifique à ces méthodes…

Récupérer les informations sur les fuseaux horaires est une chose intéressante, mais il est aussi important de pouvoir se connecter à un serveur de temps pour mettre à l'heure son PC.
Nous allons voir cela dans le prochain chapitre… :-)

IV-B. Mise à l'heure du système au moyen d'un serveur de temps

Comme vous avez pu le voir dans les chapitres précédents, Internet et Intranet offrent la possibilité de mettre à l'heure les systèmes au moyen de serveurs de temps.

Ces serveurs de temps utilisant des protocoles différents, la VCL de Delphi s'est dotée de différents composants adaptés à ces protocoles. Si vous avez un trou de mémoire, retournez voir le chapitre « Les protocoles » Réseau« utilisés par les serveurs de temps »Les protocoles "réseau" utilisés par les serveurs de temps… ;-)

Les composants « FastNet » disparaissant de Delphi 7, je ne vais pas m'étendre sur l'utilisation de ces composants, leur fonctionnement étant relativement simple. Cependant, comme je suis bon prince, vous trouverez des exemples à télécharger avec ce tutoriel…

Pour tous ces exemples, nous utiliserons la même interface et nous nous contenterons de changer les composants d'interrogation des serveurs de temps :

Aperçu de la fiche frmMain

De plus, afin d'uniformiser tous les exemples, la liste des serveurs de temps sera toujours stockée dans un fichier au format texte nommé « timeservers.txt ».

Je ne vous ferai pas l'affront de vous prévenir que pour tester ces sources, il faut évidemment être connecté à Internet !!! ;-)

Allez, testons ces composants…

IV-B-1. Utilisation des composants TIdTime et TIdDayTime (Indy)

Ces composants utilisent les protocoles Time Protocol et DayTime Protocol.

Palette

Composant

Indy

TIdTime

TIdTime

Indy

TIdDayTime

TIdDayTime

Le seul serveur de ce type actuellement disponible est le serveur time.nist.gov.
Nous interrogerons ce serveur de temps via le port 13.

Je vous invite à consulter le format de chaîne utilisé par ce serveur pour renvoyer les informations de date et d'heure sur le site du NIST :
http://www.boulder.nist.gov/timefreq/service/its.htm.
En effet, ces informations sont nécessaires pour élaborer votre routine d'affichage des informations au format local.

Pour interroger ce serveur de temps, il est indispensable de renseigner certaines propriétés du composant TIdDayTime :

  • Host : il s'agit de l'adresse ou de l'alias du serveur de temps (Exemple : time.nist.gov) ;
  • Port : il s'agit du port via lequel il est possible d'interroger le serveur de temps (Exemple : 13).

La valeur qui nous intéresse est renvoyée via la propriété DayTimeStr du composant TIdDayTime.

Maintenant que vous avez les principales informations nécessaires à la compréhension des sources, vous pouvez les télécharger et les tester à votre guise :

Télécharger les sources de TIdDayTimeDemo

Continuons notre voyage dans le temps avec les composants utilisant le protocole Simple Network Time Protocol…

IV-B-2. Utilisation du composant TIdSNTP (Indy)

Le composant TIdSNTP disponible sous Delphi 6 possède de nombreux bogues et ne fonctionne pas correctement.

Aussi, pour tester cet exemple, vous devez télécharger la version 9.0 de la suite Indy sur le site de Nevrona :

Télécharger une des versions récentes de Indy

Si vous avez mis à jour vos composants Indy, nous allons pouvoir utiliser le composant TIdSNTP qui utilise le protocole Simple Network Time Protocol.

Palette

Composant

Indy

TIdSNTP

TIdSNTP

De nombreux serveurs utilisant ce protocole sont disponibles sur Internet.
Pour en avoir la liste, consultez la page des liensOuvrages et adresses Internet utiles de ce tutoriel. Lisez bien les conditions d'accès à ces serveurs…

Je vous rappelle qu'en tant que poste « Client », vous devez uniquement vous connecter à des serveurs de temps secondaires (« Strate 2 »).

Nous interrogerons ces serveurs via le port 123.

Voici les propriétés du composant TIdSNTP à renseigner pour interroger un de ces serveurs de temps :

  • Host : il s'agit de l'adresse ou de l'alias du serveur de temps (Exemple : ntp.univ-lyon1.fr) ;
  • Port : il s'agit du port via lequel il est possible d'interroger le serveur de temps (Exemple : 123).

La valeur qui nous intéresse est renvoyée via la propriété DayTime.

Maintenant que vous avez les principales informations nécessaires à la compréhension des sources, vous pouvez les télécharger et les tester à votre guise :

Télécharger les sources de TIdSNTPDemo

Je vous laisse le loisir d'étudier les autres propriétés de ces composants.
Si vous désirez plus amples informations sur tous les domaines abordés dans ce tutoriel, je vous ai sélectionné quelques sites intéressants…


précédentsommairesuivant

Copyright © 2003 Stéphane Vaillant. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.