保存と復元のタイム ゾーンSaving and restoring time zones

TimeZoneInfoクラスが定義済みのタイム ゾーン データを取得する、レジストリに依存します。The TimeZoneInfo class relies on the registry to retrieve predefined time zone data. ただし、レジストリは、動的な構造です。However, the registry is a dynamic structure. さらに、レジストリが含まれているタイム ゾーン情報は、現在の年の時刻の調整および変換を処理するには、主に、オペレーティング システムによって使用されます。Additionally, the time zone information that the registry contains is used by the operating system primarily to handle time adjustments and conversions for the current year. これは、正確なタイム ゾーン データに依存するアプリケーションの 2 つの主要な影響があります。This has two major implications for applications that rely on accurate time zone data:

  • アプリケーションで必要とされるタイム ゾーンは、レジストリで、定義されていない可能性があります。 または名前が変更されているか、レジストリから削除します。A time zone that is required by an application may not be defined in the registry, or it may have been renamed or removed from the registry.

  • レジストリで定義されているタイム ゾーンには、履歴のタイム ゾーンの変換に必要な特定の調整規則の情報が不足している可能性があります。A time zone that is defined in the registry may lack information about the particular adjustment rules that are necessary for historical time zone conversions.

TimeZoneInfoクラス (保存) をシリアル化および逆シリアル化のタイム ゾーンのデータを (復元) のサポートにより、これらの制限に対処します。The TimeZoneInfo class addresses these limitations through its support for serialization (saving) and deserialization (restoring) of time zone data.

タイム ゾーンのシリアル化および逆シリアル化Time zone serialization and deserialization

保存とタイム ゾーンのデータをシリアル化およびタイム ゾーンを復元するには、2 つのメソッド呼び出しが含まれます。Saving and restoring a time zone by serializing and deserializing time zone data involves just two method calls:

  • シリアル化することができます、TimeZoneInfoを呼び出してそのオブジェクトのオブジェクトToSerializedStringメソッドです。You can serialize a TimeZoneInfo object by calling that object's ToSerializedString method. メソッドは、パラメーターを受け取らないし、タイム ゾーン情報を含む文字列を返します。The method takes no parameters and returns a string that contains time zone information.

  • 逆シリアル化することができます、TimeZoneInfoオブジェクトには、その文字列を渡すことによってシリアル化された文字列から、 static (Shared Visual Basic で)TimeZoneInfo.FromSerializedStringメソッドです。You can deserialize a TimeZoneInfo object from a serialized string by passing that string to the static (Shared in Visual Basic) TimeZoneInfo.FromSerializedString method.

シリアル化および逆シリアル化のシナリオSerialization and deserialization scenarios

保存 (またはシリアル化) する機能、TimeZoneInfoオブジェクトを文字列と復元 (または逆シリアル化)、後で使用できるユーティリティとの柔軟性の両方が増加、TimeZoneInfoクラスです。The ability to save (or serialize) a TimeZoneInfo object to a string and to restore (or deserialize) it for later use increases both the utility and the flexibility of the TimeZoneInfo class. ここでは、一部のシリアル化および逆シリアル化は最も有用な状況について説明します。This section examines some of the situations in which serialization and deserialization are most useful.

シリアル化して、アプリケーションでのタイム ゾーン データを逆シリアル化Serializing and deserializing time zone data in an application

必要な場合、文字列からシリアル化されたタイム ゾーンを復元することができます。A serialized time zone can be restored from a string when it is needed. レジストリから取得されたタイム ゾーンが特定の日付範囲内での日付を正しく変換できない場合は、アプリケーションでこれを行うことがあります。An application might do this if the time zone retrieved from the registry is unable to correctly convert a date and time within a particular date range. Windows XP のレジストリのタイム ゾーン データでは、通常、Windows Vista のレジストリで定義されているタイム ゾーンは約 2 つの調整規則の情報を提供します、単一の調整規則をサポートしています。For example, time zone data in the Windows XP registry supports a single adjustment rule, while time zones defined in the Windows Vista registry typically provide information about two adjustment rules. これは、過去の時刻の変換が不正確であることを意味します。This means that historical time conversions may be inaccurate. シリアル化とタイム ゾーンのデータの逆シリアル化は、この制限を処理できます。Serialization and deserialization of time zone data can handle this limitation.

次の例では、カスタムTimeZoneInfo米国を表すための調整規則がないクラスが定義されています。東部標準時のゾーンは 1883 1917、米国の州の夏時間の導入前にします。In the following example, a custom TimeZoneInfo class that has no adjustment rules is defined to represent the U.S. Eastern Standard Time zone from 1883 to 1917, before the introduction of daylight saving time in the United States. カスタムのタイム ゾーンがグローバル スコープを持つ変数にシリアル化されます。The custom time zone is serialized in a variable that has global scope. タイム ゾーンの変換メソッドConvertUtcTimeは変換する世界協定世界時 (UTC) の時間に渡されます。The time zone conversion method, ConvertUtcTime, is passed Coordinated Universal Time (UTC) times to convert. 日付と時刻は、1917年またはそれ以前に発生する場合、カスタム東部標準時ゾーンはシリアル化された文字列から復元され、レジストリから取得されたタイム ゾーンが置き換えられます。If the date and time occurs in 1917 or earlier, the custom Eastern Standard Time zone is restored from a serialized string and replaces the time zone retrieved from the registry.

using System;

public class TimeZoneSerialization
{
   static string serializedEst;
   
   public static void Main()
   {
      // Retrieve Eastern Standard Time zone from registry
      try
      {
         TimeZoneSerialization tzs = new TimeZoneSerialization();
         TimeZoneInfo est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
         // Create custom Eastern Time Zone for historical (pre-1918) conversions
         CreateTimeZone();
         // Call conversion function with one current and one pre-1918 date and time
         Console.WriteLine(ConvertUtcTime(DateTime.UtcNow, est));
         Console.WriteLine(ConvertUtcTime(new DateTime(1900, 11, 15, 9, 32, 00, DateTimeKind.Utc), est));
      }
      catch (TimeZoneNotFoundException)
      {
         Console.WriteLine("The Eastern Standard Time zone is not in the registry.");
      }
      catch (InvalidTimeZoneException)
      {
         Console.WriteLine("Data on the Eastern Standard Time Zone in the registry is corrupted.");
      }   
   }

   private static void CreateTimeZone()
   {
      // Create a simple Eastern Standard time zone 
      // without adjustment rules for 1883-1918
      TimeZoneInfo earlyEstZone = TimeZoneInfo.CreateCustomTimeZone("Eastern Standard Time", 
                                      new TimeSpan(-5, 0, 0), 
                                      " (GMT-05:00) Eastern Time (United States)",  
                                      "Eastern Standard Time");
      serializedEst = earlyEstZone.ToSerializedString();                        
   }
   
   private static DateTime ConvertUtcTime(DateTime utcDate, TimeZoneInfo tz) 
   {
      // Use time zone object from registry 
      if (utcDate.Year > 1917)
      {
         return TimeZoneInfo.ConvertTimeFromUtc(utcDate, tz);
      }   
      // Handle dates before introduction of DST
      else
      {
         // Restore serialized time zone object
         tz = TimeZoneInfo.FromSerializedString(serializedEst);
         return TimeZoneInfo.ConvertTimeFromUtc(utcDate, tz);
      }      
   }
}
Module TimeZoneSerialization
   Dim serializedEst As String
   
   Public Sub Main()
      ' Retrieve Eastern Standard Time zone from registry
      Try
         Dim est As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
         ' Create custom Eastern Time Zone for historical (pre-1918) conversions
         CreateTimeZone()
         ' Call conversion function with one current and one pre-1918 date and time
         Console.WriteLine(ConvertUtcTime(Date.UtcNow, est))
         Console.WriteLine(ConvertUtcTime(New Date(1900, 11, 15, 9, 32, 00, DateTimeKind.Utc), est))
      Catch e As TimeZoneNotFoundException
         Console.WriteLine("The Eastern Standard Time zone is not in the registry.")
      Catch e As InvalidTimeZoneException
         Console.WriteLine("Data on the Eastern Standard Time Zone in the registry is corrupted.")
      End Try   
   End Sub
   
   Private Sub CreateTimeZone()
      ' Create a simple Eastern Standard time zone 
      ' without adjustment rules for 1883-1918
      Dim earlyEstZone As TimeZoneInfo = TimeZoneInfo.CreateCustomTimeZone("Eastern Standard Time", _
                                      New TimeSpan(-5, 0, 0), _
                                      " (GMT-05:00) Eastern Time (United States)", _ 
                                      "Eastern Standard Time")
      serializedEst = earlyEstZone.ToSerializedString()                                
   End Sub
   
   Private Function ConvertUtcTime(utcDate As Date, tz As TimeZoneInfo) As Date
      ' Use time zone object from registry 
      If Year(utcDate) > 1917 Then
         Return TimeZoneInfo.ConvertTimeFromUtc(utcDate, tz)
      ' Handle dates before introduction of DST
      Else
         ' Restore serialized time zone object
         tz = TimeZoneInfo.FromSerializedString(serializedEst)
         Return TimeZoneInfo.ConvertTimeFromUtc(utcDate, tz)
      End If      
   End Function
End Module

タイム ゾーンの例外を処理Handling time zone exceptions

レジストリは動的な構造であるため、その内容は次偶発的または意図的な変更される可能性があります。Because the registry is a dynamic structure, its contents are subject to accidental or deliberate modification. つまり、レジストリで定義されている必要があり、正常に実行するアプリケーションに必要なタイム ゾーンが存在しない可能性があります。This means that a time zone that should be defined in the registry and that is required for an application to execute successfully may be absent. タイム ゾーンのシリアル化および逆シリアル化をサポートせず、その結果を処理するが、ほとんどの選択肢があるTimeZoneNotFoundExceptionアプリケーションを終了しています。Without support for time zone serialization and deserialization, you have little choice but to handle the resulting TimeZoneNotFoundException by ending the application. ただし、タイム ゾーンのシリアル化および逆シリアル化を使用することができますを処理する、予期しないTimeZoneNotFoundException復元することによって、シリアル化された文字列と、アプリケーションから必要なタイム ゾーンは引き続き実行します。However, by using time zone serialization and deserialization, you can handle an unexpected TimeZoneNotFoundException by restoring the required time zone from a serialized string, and the application will continue to run.

次の例では、作成し、カスタム中部標準時ゾーンのシリアル化します。The following example creates and serializes a custom Central Standard Time zone. 中部標準時ゾーンのレジストリから取得が試行されます。It then tries to retrieve the Central Standard Time zone from the registry. 取得操作では、いずれかがスローされた場合、TimeZoneNotFoundExceptionまたはInvalidTimeZoneException、例外ハンドラーは、タイム ゾーンを逆シリアル化します。If the retrieval operation throws either a TimeZoneNotFoundException or an InvalidTimeZoneException, the exception handler deserializes the time zone.

using System;
using System.Collections.Generic;

public class TimeZoneApplication
{
   // Define collection of custom time zones
   private Dictionary<string, string> customTimeZones = new Dictionary<string, string>();
   private TimeZoneInfo cst;
   
   public TimeZoneApplication()
   {
      // Create custom Central Standard Time 
      //
      // Declare necessary TimeZoneInfo.AdjustmentRule objects for time zone
      TimeZoneInfo customTimeZone;
      TimeSpan delta = new TimeSpan(1, 0, 0);
      TimeZoneInfo.AdjustmentRule adjustment;
      List<TimeZoneInfo.AdjustmentRule> adjustmentList = new List<TimeZoneInfo.AdjustmentRule>();
      // Declare transition time variables to hold transition time information
      TimeZoneInfo.TransitionTime transitionRuleStart, transitionRuleEnd;

      // Define end rule (for 1976-2006)
      transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 10, 5, DayOfWeek.Sunday);
      // Define rule (1976-1986)
      transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 04, 05, DayOfWeek.Sunday);
      adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1976, 1, 1), new DateTime(1986, 12, 31), delta, transitionRuleStart, transitionRuleEnd);
      adjustmentList.Add(adjustment);
      // Define rule (1987-2006)  
      transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 04, 01, DayOfWeek.Sunday);
      adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1987, 1, 1), new DateTime(2006, 12, 31), delta, transitionRuleStart, transitionRuleEnd);
      adjustmentList.Add(adjustment);
      // Define rule (2007- )  
      transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 03, 02, DayOfWeek.Sunday);
      transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 11, 01, DayOfWeek.Sunday);
      adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(2007, 01, 01), DateTime.MaxValue.Date, delta, transitionRuleStart, transitionRuleEnd);
      adjustmentList.Add(adjustment);
                    
      // Create custom U.S. Central Standard Time zone         
      customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Central Standard Time", 
                      new TimeSpan(-6, 0, 0), 
                      "(GMT-06:00) Central Time (US Only)", "Central Standard Time", 
                      "Central Daylight Time", adjustmentList.ToArray());       
      // Add time zone to collection
      customTimeZones.Add(customTimeZone.Id, customTimeZone.ToSerializedString());                           

      // Create any other required time zones     
   }

   public static void Main()
   {
      TimeZoneApplication tza = new TimeZoneApplication();
      tza.AppEntryPoint();
   }
   
   private void AppEntryPoint()
   {
      try
      {
         cst = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
      }   
      catch (TimeZoneNotFoundException)
      {
         if (customTimeZones.ContainsKey("Central Standard Time"))
            HandleTimeZoneException("Central Standard Time");
      }
      catch (InvalidTimeZoneException)
      {
         if (customTimeZones.ContainsKey("Central Standard Time"))
            HandleTimeZoneException("Central Standard Time");
      }               
      if (cst == null)
      {
         Console.WriteLine("Unable to load Central Standard Time zone.");
         return;
      }
      DateTime currentTime = DateTime.Now;
      Console.WriteLine("The current {0} time is {1}.", 
                        TimeZoneInfo.Local.IsDaylightSavingTime(currentTime) ? 
                            TimeZoneInfo.Local.StandardName : 
                            TimeZoneInfo.Local.DaylightName, 
                        currentTime.ToString("f"));
      Console.WriteLine("The current {0} time is {1}.", 
                        cst.IsDaylightSavingTime(currentTime) ? 
                            cst.StandardName : 
                            cst.DaylightName, 
                        TimeZoneInfo.ConvertTime(currentTime, TimeZoneInfo.Local, cst).ToString("f"));
   }

   private void HandleTimeZoneException(string timeZoneName)
   {
      string tzString = customTimeZones[timeZoneName];
      cst = TimeZoneInfo.FromSerializedString(tzString);
   }
}
Imports System.Collections.Generic

Public Class TimeZoneApplication
   ' Define collection of custom time zones
   Private customTimeZones As New Dictionary(Of String, String)
   Private cst As TimeZoneInfo 
   
   Public Sub New()
      ' Define custom Central Standard Time
      '
      ' Declare necessary TimeZoneInfo.AdjustmentRule objects for time zone
      Dim customTimeZone As TimeZoneInfo
      Dim delta As New TimeSpan(1, 0, 0)
      Dim adjustment As TimeZoneInfo.AdjustmentRule
      Dim adjustmentList As New List(Of TimeZoneInfo.AdjustmentRule)
      ' Declare transition time variables to hold transition time information
      Dim transitionRuleStart, transitionRuleEnd As TimeZoneInfo.TransitionTime

      ' Define end rule (for 1976-2006)
      transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#02:00:00AM#, 10, 5, DayOfWeek.Sunday)
      ' Define rule (1976-1986)
      transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 04, 05, DayOfWeek.Sunday)
      adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1976#, #12/31/1986#, delta, transitionRuleStart, transitionRuleEnd)
      adjustmentList.Add(adjustment)
      ' Define rule (1987-2006)  
      transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 04, 01, DayOfWeek.Sunday)
      adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1987#, #12/31/2006#, delta, transitionRuleStart, transitionRuleEnd)
      adjustmentList.Add(adjustment)
      ' Define rule (2007- )  
      transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 03, 02, DayOfWeek.Sunday)
      transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 11, 01, DayOfWeek.Sunday)
      adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/2007#, Date.MaxValue.Date, delta, transitionRuleStart, transitionRuleEnd)
      adjustmentList.Add(adjustment)
      ' Create custom time zone
      customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Central Standard Time", _
                      New TimeSpan(-6, 0, 0), _
                      "(GMT-06:00) Central Time (US Only)", "Central Standard Time", _
                      "Central Daylight Time", adjustmentList.ToArray())
      ' Add time zone to collection
      customTimeZones.Add(customTimeZone.Id, customTimeZone.ToSerializedString())                           

      ' Create any other required time zones     
   End Sub
   
   Public Shared Sub Main()
      Dim tza As New TimeZoneApplication()
      tza.AppEntryPoint()
   End Sub
   
   Private Sub AppEntryPoint()
      Try
         cst = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
      Catch e As TimeZoneNotFoundException
         If customTimeZones.ContainsKey("Central Standard Time")
            HandleTimeZoneException("Central Standard Time")
         End If
      Catch e As InvalidTimeZoneException
         If customTimeZones.ContainsKey("Central Standard Time")
            HandleTimeZoneException("Central Standard Time")
         End If
      End Try               
      If cst Is Nothing Then
         Console.WriteLine("Unable to load Central Standard Time zone.")
         Return
      End If
      Dim currentTime As Date = Date.Now
      Console.WriteLine("The current {0} time is {1}.", _
                        IIf(TimeZoneInfo.Local.IsDaylightSavingTime(currentTime), _
                            TimeZoneInfo.Local.StandardName, _
                            TimeZoneInfo.Local.DaylightName), _
                        currentTime.ToString("f"))
      Console.WriteLine("The current {0} time is {1}.", _
                        IIf(cst.IsDaylightSavingTime(currentTime), _
                            cst.StandardName, _
                            cst.DaylightName), _
                        TimeZoneInfo.ConvertTime(currentTime, TimeZoneInfo.Local, cst).ToString("f"))
   End Sub
   
   Private Sub HandleTimeZoneException(timeZoneName As String)
      Dim tzString As String = customTimeZones.Item(timeZoneName)
      cst = TimeZoneInfo.FromSerializedString(tzString)
   End Sub
End Class

シリアル化された文字列を格納して、必要なときにそれを復元します。Storing a serialized string and restoring it when needed

前の例では、文字列変数にタイム ゾーン情報を格納し、必要なときにこれを復元します。The previous examples have stored time zone information to a string variable and restored it when needed. ただし、シリアル化されたタイム ゾーン情報自体に格納できる、外部のファイル、リソース ファイルなど、いくつかのストレージ メディアを格納する文字列は、アプリケーション、またはレジストリに埋め込まれます。However, the string that contains serialized time zone information can itself be stored in some storage medium, such as an external file, a resource file embedded in the application, or the registry. (カスタム タイム ゾーンに関する情報をレジストリで、システムのタイム ゾーンのキーとは別に保存するかを注意してください)。(Note that information about custom time zones should be stored apart from the system's time zone keys in the registry.)

この方法でシリアル化されたタイム ゾーン文字列を格納すると、タイム ゾーンの作成ルーチンも、アプリケーション自体とは別になります。Storing a serialized time zone string in this manner also separates the time zone creation routine from the application itself. たとえば、タイム ゾーンの作成ルーチンは実行し、アプリケーションが使用できる履歴タイム ゾーン情報を含むデータ ファイルを作成できます。For example, a time zone creation routine can execute and create a data file that contains historical time zone information that an application can use. データ ファイルを指定できます、アプリケーションと共にインストールして開くことがし、1 つまたは複数のタイム ゾーンの逆シリアル化できます、アプリケーションで必要なときにします。The data file can be then be installed with the application, and it can be opened and one or more of its time zones can be deserialized when the application requires them.

タイム ゾーンのシリアル化されたデータを保存する埋め込みリソースを使用する例は、次を参照してください。する方法: 埋め込みリソースにタイム ゾーンを保存する方法: 埋め込みリソースからタイム ゾーンを復元です。For an example that uses an embedded resource to store serialized time zone data, see How to: Save time zones to an embedded resource and How to: Restore time zones from an embedded resource.

関連項目See also

日付、時刻、およびタイム ゾーンDates, times, and time zones