Sdílet prostřednictvím


Postupy: Uložit časová pásma do integrovaného prostředku

Aplikace zohledňující časová pásma často vyžaduje přítomnost určitého časového pásma. Ale protože dostupnost jednotlivých objektů TimeZoneInfo závisí na informacích uložených v registru místního systému, mohou chybět dokonce i běžně dostupná časová pásma. Navíc informace o vlastních časových pásmech, jejichž instance byla vytvořena pomocí metody CreateCustomTimeZone, nejsou uloženy do registru společně s informacemi jiných časových pásem. Chcete-li zajistit, aby tato časová pásma byla k dispozici v případě potřeby, můžete je uložit pomocí jejich serializace a později je obnovit pomocí jejich rekonstrukce.

Obvykle k serializaci objektu TimeZoneInfo dochází mimo aplikaci zohledňující časová pásma. V závislosti na úložišti dat používaného k ukládání serializovaných objektů TimeZoneInfo mohou být data časových pásem serializována jako součást instalační rutiny (například pokud jsou data uložena v klíči registru aplikace) nebo jako součást obslužné rutiny, která se spouští před zkompilováním konečné aplikace (například pokud jsou serializovaná data uložena v XML souboru prostředků (.resx) technologie .NET.

Kromě souboru prostředků, který je zkompilován s aplikací, lze pro informace časových pásem využít několik dalších datových úložišť. Například:

  • Registr. Mějte na paměti, že by aplikace měla pro ukládání dat vlastních časových pásem používat podklíče svého vlastního aplikačního klíče spíše než podklíče HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.

  • Konfigurační soubory.

  • Jiné systémové soubory.

Chcete-li uložit časové pásmo pomocí jeho serializace do souboru .resx

  1. Načtěte existující časové pásmo nebo vytvořte nové časové pásmo.

    Informace o načtení existujícího časového pásma naleznete v tématu Postupy: Přístup k předdefinovaných objektům místních časových zón a zóny UTC a Postupy: Vytvoření instance objektu TimeZoneInfo.

    Chcete-li vytvořit nové časové pásmo, zavolejte jedno z přetížení metody CreateCustomTimeZone. Další informace naleznete v tématu Postupy: Vytváření časových pásem bez pravidel úprav a Postupy: Vytváření časových pásem s pravidly úprav.

  2. Chcete-li vytvořit řetězec, který obsahuje data časového pásma, zavolejte metodu ToSerializedString.

  3. Vytvořte instanci objektu StreamWriter poskytnutím názvu a volitelně cesty k souboru .resx konstruktoru třídy StreamWriter.

  4. Vytvořte instanci objektu ResXResourceWriter předáním objektu StreamWriter konstruktoru třídy ResXResourceWriter.

  5. Předejte serializovaný řetězec časového pásma metodě ResXResourceWriter.AddResource.

  6. Volejte metodu ResXResourceWriter.Generate.

  7. Volejte metodu ResXResourceWriter.Close.

  8. Zavřete objekt StreamWriter voláním jeho metody Close.

  9. Přidejte vytvořený soubor .resx k danému projektu aplikace Visual Studio.

  10. Pomocí okna Vlastnosti v aplikaci Visual Studio se ujistěte, že vlastnost Proces sestavení souboru .resx je nastavena na hodnotu Integrovaný prostředek.

Příklad

V následujícím příkladu jsou objekt TimeZoneInfo, který představuje čas UTC a objekt TimeZoneInfo představující čas ve stanici Palmer na Antarktidě serializovány do XML souboru prostředků technologie .NET s názvem SerializedTimeZones.resx. Čas UTC je obvykle definován v registru, čas stanice Palmer na Antarktidě je vlastní časové pásmo.

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();
}

V tomto příkladu jsou objekty TimeZoneInfo serializovány tak, aby byly k dispozici v souboru prostředků v době kompilace.

Protože metoda ResXResourceWriter.Generate přidá do XML souboru prostředků technologie .NET úplné informace hlavičky, nelze ji použít k přidání prostředků do již existujícího souboru. V příkladu je výše zmíněné ošetřeno pomocí kontroly souboru SerializedTimeZones.resx a pokud existuje, pomocí uložení všech jeho prostředků jiných než daná dvě serializovaná časová pásma do obecného objektu Dictionary<TKey, TValue>. Stávající soubor je poté odstraněn a existující prostředky jsou přidány do nového souboru SerializedTimeZones.resx. Serializovaná data časových pásem jsou do tohoto souboru přidána také.

Položka klíč (nebo Název) prostředků nesmí obsahovat mezery. Metoda Replace(String, String) je volána pro odebrání všech vložených mezer v identifikátorech časového pásma, dříve než jsou přiřazeny k souboru prostředků.

Probíhá kompilace kódu

Tento příklad vyžaduje:

  • Aby byl přidán do projektu odkaz na System.Windows.Forms.dll a System.Core.dll.

  • Aby byly importované následující obory názvů:

    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;
    

Viz také

Úkoly

Postupy: Obnovení časových pásem z integrovaného zdroje

Koncepty

Přehled časových pásem

Další zdroje

Data, časy a časových pásem