共用方式為


HOW TO:將時區儲存到內嵌資源

更新:2007 年 11 月

時區感知應用程式通常需要特定的時區。但是,因為個別 TimeZoneInfo 物件的可用性必須視本機系統登錄中所儲存的資訊而定,所以即使自訂可用的時區也可能不存在。此外,使用 CreateCustomTimeZone 方法具現化的自訂時區相關資訊,並不會和其他時區資訊一起儲存在登錄中。如果要確保這些時區在需要時可以使用,您可以將時區序列化加以儲存,稍後再還原序列化以還原時區。

一般而言,將 TimeZoneInfo 物件序列化與時區感知應用程式無關。視用來保存序列化 TimeZoneInfo 物件的資料存放區而定,時區資料可能會被序列化成為設定或安裝常式的一部分 (例如,當資料儲存在登錄的應用程式索引鍵中),或成為編譯最終應用程式前所執行的公用程式常式的一部分 (例如,當序列化資料存放在 .NET XML 資源 (.resx) 檔中時)。

除了以應用程式編譯的資源檔外,還有幾個其他資料存放區可用來存放時區資訊。這些控制項包括下列各項:

  • 登錄。請注意,應用程式應使用自己的應用程式索引鍵的子機碼,儲存自訂時區資料,而不是使用 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones 的子機碼。

  • 組態檔。

  • 其他系統檔案。

將時區序列化成 .resx 檔案以儲存時區

  1. 擷取現有時區,或建立新的時區。

    如果要擷取現有時區,請參閱 HOW TO:存取預先定義的 UTC 和本機時區物件HOW TO:具現化 TimeZoneInfo 物件

    如果要建立新的時區,請呼叫下列 CreateCustomTimeZone 方法的其中一個多載。如需詳細資訊,請參閱 HOW TO:建立沒有調整規則的時區HOW TO:建立有調整規則的時區

  2. 呼叫 ToSerializedString 方法以建立內含時區資料的字串。

  3. 提供 .resx 檔案的名稱 (或路徑) 給 StreamWriter 類別建構函式,將 StreamWriter 物件具現化。

  4. StreamWriter 物件傳送給 ResXResourceWriter 類別建構函式,將 ResXResourceWriter 物件具現化。

  5. 將時區的序列化字串傳送給 ResXResourceWriter.AddResource 方法。

  6. 呼叫 ResXResourceWriter.Generate 方法。

  7. 呼叫 ResXResourceWriter.Close 方法。

  8. 呼叫 StreamWriter 物件的 Close 方法,即可關閉物件。

  9. 將產生的 .resx 檔案新增至應用程式的 Visual Studio 專案中。

  10. 使用 Visual Studio 中的 [屬性] 視窗,確認 .resx 檔案的 [建置動作] 屬性設定為 [內嵌資源]。

範例

下列範例將代表「中央標準時間」的 TimeZoneInfo 物件,以及代表「南極科學研究站」時間的 TimeZoneInfo 物件,序列化成名稱為 SerializedTimeZones.resx 的 .NET XML 資源檔。「中央標準時間」通常定義在登錄中,「南極科學研究站」則是自訂時區。

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

這個範例會將 TimeZoneInfo 物件序列化,這樣編譯時資源檔就可以使用。

因為 ResXResourceWriter.Generate 方法會將完整的標頭資訊新增至 .NET XML 資源檔,所以不能用來將資源新增至現有檔案。範例中處理的方法,是檢查 SerializedTimeZones.resx 檔案,如果有這個檔案,則除了這兩個序列化的時區外,會將所有其他資源儲存至泛型 Dictionary<TKey, TValue> 物件。然後就會刪除現有檔案,新增現有資源至新的 SerializedTimeZones.resx 檔案。序列化的時區資料也會新增至這個檔案。

資源的索引鍵 (或 [名稱]) 欄位不應包含空白字元。在時區識別項被指派給資源檔前,呼叫 Replace(String, String) 方法以移除識別項中所有的空白字元。

編譯程式碼

這個範例需要:

  • 將 System.Windows.Forms.dll 的參考及 System.Core.dll 新增至專案。

  • 匯入下列命名空間:

    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;
    

請參閱

工作

HOW TO:從內嵌資源還原時區

概念

時區概觀

其他資源

時間和時區