Partager via


Comment : enregistrer des fuseaux horaires dans une ressource incorporée

Mise à jour : novembre 2007

Une application prenant en charge les fuseaux horaires requiert généralement la présence d'un fuseau horaire particulier. Toutefois, comme la disponibilité d'objets TimeZoneInfo individuels dépend d'informations stockées dans le Registre du système local, même les fuseaux horaires habituellement disponibles peuvent être absents. De plus, les informations sur les fuseaux horaires personnalisés instanciés à l'aide de la méthode CreateCustomTimeZone ne sont pas stockées avec d'autres informations de fuseau horaire dans le Registre. Pour que ces fuseaux horaires soient disponibles lorsque vous en avez besoin, vous pouvez les enregistrer en les sérialisant puis les restaurer en les désérialisant.

En général, la sérialisation d'un objet TimeZoneInfo se produit en dehors de l'application prenant en charge les fuseaux horaires. Selon le magasin de données utilisé pour accueillir les objets TimeZoneInfo sérialisés, les données de fuseau horaire peuvent être sérialisées dans le cadre d'une routine d'installation ou de configuration (par exemple, lorsque les données sont stockées dans une clé du Registre relative à une application) ou d'une routine d'utilitaire qui s'exécute avant la compilation de l'application finale (par exemple, lorsque les données sérialisées sont stockées dans un fichier de ressources (.resx) .NET XML).

Outre un fichier de ressources qui est compilé avec l'application, plusieurs autres magasins de données peuvent être utilisés pour contenir les informations de fuseau horaire, et notamment :

  • le Registre ; à noter qu'une application doit utiliser les sous-clés de sa propre clé d'application pour stocker des données de fuseau horaire personnalisées plutôt que les sous-clés de HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.

  • les fichiers de configuration ;

  • d'autres fichiers système.

Pour enregistrer un fuseau horaire en le sérialisant dans un fichier .resx

  1. Récupérez un fuseau horaire existant ou créez un fuseau horaire.

    Pour récupérer un fuseau horaire existant, consultez Comment : accéder aux objets UTC et aux objets de fuseau horaire local prédéfinis et Comment : instancier un objet TimeZoneInfo.

    Pour créer un fuseau horaire, appelez l'une des surcharges de la méthode CreateCustomTimeZone. Pour plus d'informations, consultez Comment : créer des fuseaux horaires sans règles d'ajustement et Comment : créer des fuseaux horaires avec des règles d'ajustement.

  2. Appelez la méthode ToSerializedString pour créer une chaîne qui contient les données du fuseau horaire.

  3. Instanciez un objet StreamWriter en fournissant le nom et éventuellement le chemin d'accès du fichier .resx au constructeur de classe StreamWriter.

  4. Instanciez un objet ResXResourceWriter en passant l'objet StreamWriter au constructeur de classe ResXResourceWriter.

  5. Passez la chaîne sérialisée du fuseau horaire à la méthode ResXResourceWriter.AddResource.

  6. Appelez la méthode ResXResourceWriter.Generate.

  7. Appelez la méthode ResXResourceWriter.Close.

  8. Fermez l'objet StreamWriter en appelant sa méthode Close.

  9. Ajoutez le fichier .resx généré au projet Visual Studio de l'application.

  10. Dans la fenêtre Propriétés de Visual Studio, assurez-vous que la propriété Build Action du fichier .resx a la valeur Ressource incorporée.

Exemple

L'exemple suivant sérialise un objet TimeZoneInfo qui représente l'heure du Centre des États-Unis et un objet TimeZoneInfo qui représente l'heure de la station de Palmer, en Antarctique, dans un fichier de ressources .NET XML nommé SerializedTimeZones.resx. L'heure du Centre est généralement définie dans le Registre. La station de Palmer, en Antarctique, est un fuseau horaire personnalisé.

Private Sub SerializeTimeZones()
   Dim writeStream As TextWriter
   Dim resources As New Dictionary(Of String, String)
   ' Determine if .resx file exists
   If File.Exists(resxName) Then
      ' Open reader
      Dim readStream As TextReader = New StreamReader(resxName)
      Dim resReader As New ResXResourceReader(readStream)
      For Each item As DictionaryEntry In resReader
         If Not (CStr(item.Key) = "CentralStandardTime" Or _
                 CStr(item.Key) = "PalmerStandardTime") Then
            resources.Add(CStr(item.Key), CStr(item.Value))
         End If
      Next
      readStream.Close()
      ' Delete file, since write method creates duplicate xml headers
      File.Delete(resxName)
   End If

   ' Open stream to write to .resx file
   Try
      writeStream = New StreamWriter(resxName, True)
   Catch e As FileNotFoundException
      ' Handle failure to find file
      Console.WriteLine("{0}: The file {1} could not be found.", e.GetType().Name, resxName)
      Exit Sub
   End Try

   ' Get resource writer
   Dim resWriter As ResXResourceWriter = New ResXResourceWriter(writeStream)

   ' Add resources from existing file
   For Each item As KeyValuePair(Of String, String) In resources
      resWriter.AddResource(item.Key, item.Value)
   Next
   ' Serialize Central Standard Time
   Try
      Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
      resWriter.AddResource(cst.Id.Replace(" ", String.Empty), cst.ToSerializedString())
   Catch
      Console.WriteLine("The Central Standard Time zone could not be found.")
   End Try

   ' Create time zone for Palmer, Antarctica
   '
   ' Define transition times to/from DST
   Dim startTransition As TimeZoneInfo.TransitionTime = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#4:00:00 AM#, 10, 2, DayOfWeek.Sunday)
   Dim endTransition As TimeZoneInfo.TransitionTime = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#3:00:00 AM#, 3, 2, DayOfWeek.Sunday)
   ' Define adjustment rule
   Dim delta As TimeSpan = New TimeSpan(1, 0, 0)
   Dim adjustment As TimeZoneInfo.AdjustmentRule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#10/1/1999#, Date.MaxValue.Date, delta, startTransition, endTransition)
   ' Create array for adjustment rules
   Dim adjustments() As TimeZoneInfo.AdjustmentRule = {adjustment}
   ' Define other custom time zone arguments
   Dim DisplayName As String = "(GMT-04:00) Antarctica/Palmer Time"
   Dim standardName As String = "Palmer Standard Time"
   Dim daylightName As String = "Palmer Daylight Time"
   Dim offset As TimeSpan = New TimeSpan(-4, 0, 0)
   Dim palmer As TimeZoneInfo = TimeZoneInfo.CreateCustomTimeZone(standardName, offset, DisplayName, standardName, daylightName, adjustments)
   resWriter.AddResource(palmer.Id.Replace(" ", String.Empty), palmer.ToSerializedString())

   ' Save changes to .resx file 
   resWriter.Generate()
   resWriter.Close()
   writeStream.Close()
End Sub
TimeZoneSerialization()
{
   TextWriter writeStream;
   Dictionary<string, string> resources = new Dictionary<string, string>();
   // Determine if .resx file exists
   if (File.Exists(resxName))
   {
      // Open reader
      TextReader readStream = new StreamReader(resxName);
      ResXResourceReader resReader = new ResXResourceReader(readStream);
      foreach (DictionaryEntry item in resReader)
      {
         if (! (((string) item.Key) == "CentralStandardTime" || 
                ((string) item.Key) == "PalmerStandardTime" )) 
            resources.Add((string)item.Key, (string) item.Value);
      }
      readStream.Close();
      // Delete file, since write method creates duplicate xml headers
      File.Delete(resxName);
   }

   // Open stream to write to .resx file
   try
   {
      writeStream = new StreamWriter(resxName, true);
   }
   catch (FileNotFoundException e)
   {
      // Handle failure to find file
      Console.WriteLine("{0}: The file {1} could not be found.", e.GetType().Name, resxName);
      return;
   }

   // Get resource writer
   ResXResourceWriter resWriter = new ResXResourceWriter(writeStream);

   // Add resources from existing file
   foreach (KeyValuePair<string, string> item in resources)
   {
      resWriter.AddResource(item.Key, item.Value);
   }

   // Serialize Central Standard Time
   try
   {
      TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
      resWriter.AddResource(cst.Id.Replace(" ", string.Empty), cst.ToSerializedString());
   }
   catch (TimeZoneNotFoundException)
   {
      Console.WriteLine("The Central Standard Time zone could not be found.");
   }

   // Create time zone for Palmer, Antarctica
   //
   // Define transition times to/from DST
   TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0), 
                                                                                              10, 2, DayOfWeek.Sunday);
   TimeZoneInfo.TransitionTime endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 
                                                                                            3, 2, DayOfWeek.Sunday);
   // Define adjustment rule
   TimeSpan delta = new TimeSpan(1, 0, 0);
   TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), 
                                         DateTime.MaxValue.Date, delta, startTransition, endTransition);
   // Create array for adjustment rules
   TimeZoneInfo.AdjustmentRule[] adjustments = {adjustment};
   // Define other custom time zone arguments
   string DisplayName = "(GMT-04:00) Antarctica/Palmer Time";
   string standardName = "Palmer Standard Time";
   string daylightName = "Palmer Daylight Time";
   TimeSpan offset = new TimeSpan(-4, 0, 0);
   TimeZoneInfo palmer = TimeZoneInfo.CreateCustomTimeZone(standardName, offset, DisplayName, standardName, daylightName, adjustments);
   resWriter.AddResource(palmer.Id.Replace(" ", String.Empty), palmer.ToSerializedString());

   // Save changes to .resx file 
   resWriter.Generate();
   resWriter.Close();
   writeStream.Close();
}

Cet exemple sérialise des objets TimeZoneInfo pour qu'ils soient disponibles dans un fichier de ressources à la compilation.

Comme la méthode ResXResourceWriter.Generate ajoute des informations d'en-tête complètes à un fichier de ressources .NET XML, il n'est pas possible de l'utiliser pour ajouter des ressources à un fichier existant. L'exemple gère cette situation en recherchant le fichier SerializedTimeZones.resx. S'il existe, toutes ses ressources, à l'exception des deux fuseaux horaires sérialisés, sont stockées dans un objet Dictionary<TKey, TValue> générique. Le fichier existant est ensuite supprimé et les ressources existantes sont ajoutées à un nouveau fichier SerializedTimeZones.resx. Les données de fuseau horaire sérialisées sont également ajoutées à ce fichier.

Les champs clés (ou Nom) de ressources ne doivent pas contenir d'espaces incorporés. La méthode Replace(String, String) est appelée pour supprimer tous les espaces incorporés dans les identificateurs de fuseau horaire avant qu'ils ne soient assignés au fichier de ressources.

Compilation du code

Cet exemple nécessite :

  • qu'une référence à System.Windows.Forms.dll et System.Core.dll soit ajoutée au projet.

  • que les espaces de noms suivants soient importés :

    Imports System.Globalization
    Imports System.IO
    Imports System.Reflection
    Imports System.Resources
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Resources;
    using System.Windows.Forms;
    

Voir aussi

Tâches

Comment : restaurer des fuseaux horaires dans une ressource incorporée

Concepts

Vue d'ensemble des fuseaux horaires

Autres ressources

Heures et fuseaux horaires