Condividi tramite


Procedura: salvare fusi orari in una risorsa incorporata

Aggiornamento: novembre 2007

Un'applicazione che dipende dal fuso orario richiede spesso la presenza di un determinato fuso orario. Tuttavia, poiché la disponibilità dei singoli oggetti TimeZoneInfo dipende dalle informazioni archiviate nel Registro di sistema locale, è possibile che anche i fusi orari generalmente disponibili non siano presenti. Inoltre, le informazioni sui fusi orari personalizzati di cui viene creata un'istanza mediante il metodo CreateCustomTimeZone non vengono archiviate nel Registro di sistema insieme alle altre informazioni sul fuso orario. Per assicurare che questi fusi orari siano disponibili quando necessario, è possibile salvarli serializzandoli e successivamente ripristinarli deserializzandoli.

In genere, la serializzazione di un oggetto TimeZoneInfo si verifica indipendentemente dall'applicazione che dipende dal fuso orario. A seconda dell'archivio dati utilizzato per l'archiviazione degli oggetti TimeZoneInfo serializzati, i dati del fuso orario possono essere serializzati come parte di una routine di configurazione o di installazione, ad esempio quando i dati vengono archiviati in una chiave applicazione del Registro di sistema, o come parte di una routine di utilità che viene eseguita prima della compilazione dell'applicazione finale, ad esempio quando i dati serializzati vengono archiviati in un file di risorse XML .NET (RESX).

Oltre al file di risorse compilato con l'applicazione, è possibile utilizzare molti altri archivi dati per le informazioni sul fuso orario, tra cui:

  • Registro di sistema. Notare che un'applicazione deve utilizzare le sottochiavi della relativa chiave applicazione per archiviare i dati del fuso orario personalizzato anziché utilizzare le sottochiavi di HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.

  • File di configurazione

  • Altri file di sistema

Per salvare un fuso orario serializzandolo in un file RESX

  1. Recuperare un fuso orario esistente o creare un nuovo fuso orario.

    Per recuperare un fuso orario esistente, vedere Procedura: accedere agli oggetti predefiniti dell'ora UTC e del fuso orario locale e Procedura: creare un'istanza di un oggetto TimeZoneInfo.

    Per creare un nuovo fuso orario, chiamare uno degli overload del metodo CreateCustomTimeZone. Per ulteriori informazioni, vedere Procedura: creare fusi orari senza regole di regolazione e Procedura: creare fusi orari con regole di regolazione.

  2. Chiamare il metodo ToSerializedString per creare una stringa contenente i dati del fuso orario.

  3. Creare un'istanza di un oggetto StreamWriter fornendo il nome e facoltativamente il percorso del file RESX al costruttore della classe StreamWriter.

  4. Creare un'istanza di un oggetto ResXResourceWriter passando l'oggetto StreamWriter al costruttore della classe ResXResourceWriter.

  5. Passare la stringa serializzata del fuso orario al metodo ResXResourceWriter.AddResource.

  6. Chiamare il metodo ResXResourceWriter.Generate.

  7. Chiamare il metodo ResXResourceWriter.Close.

  8. Chiudere l'oggetto StreamWriter chiamando il metodo Close.

  9. Aggiungere il file RESX generato al progetto di Visual Studio dell'applicazione.

  10. Dalla finestra Proprietà di Visual Studio verificare che la proprietà Operazione di compilazione del file RESX sia impostata su Risorsa incorporata.

Esempio

Nell'esempio seguente viene serializzato un oggetto TimeZoneInfo che rappresenta l'Ora solare fuso centrale e un oggetto TimeZoneInfo che rappresenta l'ora della stazione Palmer Station (Antartide) in un file di risorse XML .NET denominato SerializedTimeZones.resx. L'Ora solare fuso centrale viene generalmente definita nel Registro di sistema, mentre l'ora della stazione Palmer Station (Antartide) rappresenta un fuso orario personalizzato.

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

In questo esempio vengono serializzati gli oggetti TimeZoneInfo in modo da essere disponibili in un file di risorse in fase di compilazione.

Poiché il metodo ResXResourceWriter.Generate aggiunge informazioni sull'intestazione complete in un file di risorse XML .NET, non può essere utilizzato per aggiungere risorse in un file esistente. Nell'esempio tale condizione viene gestita verificando la presenza del file SerializedTimeZones.resx e, se esiste, archiviando tutte le relative risorse eccetto i due fusi orari serializzati in un oggetto Dictionary<TKey, TValue> generico. Il file esistente viene quindi eliminato e le risorse esistenti vengono aggiunte in un nuovo file SerializedTimeZones.resx. In questo file vengono inoltre aggiunti i dati dei fusi orari serializzati.

I campi chiave (o Nome) delle risorse non devono contenere spazi incorporati. Il metodo Replace(String, String) viene chiamato per rimuovere tutti gli spazi incorporati negli identificatori del fuso orario prima che vengano assegnati al file di risorse.

Compilazione del codice

Per questo esempio è necessario:

  • Aggiungere un riferimento a System.Windows.Forms.dll e System.Core.dll al progetto.

  • Importare gli spazi dei nomi seguenti:

    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;
    

Vedere anche

Attività

Procedura: ripristinare i fusi orari da una risorsa incorporata

Concetti

Panoramica sul fuso orario

Altre risorse

Ora e fusi orari