다음을 통해 공유


표준 시간대 저장 및 복원

업데이트: 2007년 11월

TimeZoneInfo 클래스는 레지스트리를 통해 미리 정의된 표준 시간대 데이터를 검색합니다. 그러나 레지스트리는 동적 구조입니다. 또한 레지스트리에 포함된 표준 시간대 정보는 운영 체제에서 기본적으로 현재 연도에 대한 시간 조정 및 변환을 처리하기 위해 사용됩니다. 이는 정확한 표준 시간대 데이터를 사용하는 응용 프로그램에 다음 두 가지 주요한 영향을 미칩니다.

  • 응용 프로그램에 필요한 표준 시간대가 레지스트리에 정의되어 있지 않거나 레지스트리에서 제거되거나 이름이 바뀌었을 수 있습니다.

  • 레지스트리에 정의되어 있는 표준 시간대에 기록 표준 시간대 변환에 필요한 특정 조정 규칙에 대한 정보가 없을 수 있습니다.

TimeZoneInfo 클래스는 표준 시간대 데이터의 serialization(저장) 및 deserialization(복원)에 대한 지원을 통해 이러한 제한 사항을 해결합니다.

표준 시간대 serialization 및 deserialization

표준 시간대 데이터를 serialize 및 deserialize하여 표준 시간대를 저장 및 복원하려면 다음과 같이 두 메서드만 호출하면 됩니다.

  • TimeZoneInfo 개체의 ToSerializedString 메서드를 호출하여 해당 개체를 serialize할 수 있습니다. 이 메서드는 매개 변수를 사용하지 않으며 표준 시간대 정보가 포함된 문자열을 반환합니다.

  • Serialize된 문자열을 static(Visual Basic의 경우 Shared) TimeZoneInfo.FromSerializedString 메서드에 전달하여 해당 문자열에서 TimeZoneInfo 개체를 deserialize할 수 있습니다.

Serialization 및 deserialization 시나리오

TimeZoneInfo 개체를 문자열로 저장 또는 serialize하고 나중에 사용하기 위해 복원 또는 deserialize하는 기능은 TimeZoneInfo 클래스의 유용성과 유연성을 향상시킵니다. 이 단원에서는 serialization 및 deserialization이 가장 유용한 몇 가지 상황을 살펴봅니다.

응용 프로그램에서 표준 시간대 데이터 serialize 및 deserialize

필요한 경우 문자열에서 serialize된 표준 시간대를 복원할 수 있습니다. 레지스트리에서 검색된 표준 시간대가 특정 날짜 범위 내의 날짜 및 시간을 올바르게 변환할 수 없는 경우에 응용 프로그램에서 복원할 수 있습니다. 예를 들어 Windows XP 레지스트리의 표준 시간대 데이터에서는 하나의 조정 규칙을 지원하는 반면 Windows Vista 레지스트리에 정의된 표준 시간대에서는 일반적으로 두 개의 조정 규칙에 대한 정보를 제공합니다. 따라서 기록 시간 변환이 잘못될 수 있습니다. 표준 시간대 데이터의 serialization 및 deserialization을 통해 이 제한 사항을 처리할 수 있습니다.

다음 예제에서는 미국의 일광 절약 시간을 도입하기 전에 1883년에서 1917년 사이의 미국 동부 표준시를 나타내는 사용자 지정 TimeZoneInfo 클래스를 조정 규칙 없이 정의합니다. 이 사용자 지정 표준 시간대는 전역 범위를 갖는 변수로 serialize됩니다. 표준 시간대 변환 메서드 ConvertUtcTime에 변환할 UTC(협정 세계시) 시간이 전달됩니다. 날짜 및 시간이 1917년 이전에 있는 경우 사용자 지정 동부 표준시가 serialize된 문자열에서 복원되고 레지스트리에서 검색된 표준 시간대를 대체합니다.

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

표준 시간대 예외 처리

레지스트리는 동적 구조이므로 해당 내용이 실수나 고의로 수정될 수 있습니다. 따라서 응용 프로그램을 성공적으로 실행하는 데 필요한 표준 시간대가 레지스트리에 정의되어 있어야 하는 데 없을 수 있습니다. 표준 시간대 serialization 및 deserialization이 지원되지 않으면 TimeZoneNotFoundException이 발생한 경우 응용 프로그램을 종료하여 이를 처리할 수밖에 없습니다. 그러나 표준 시간대 serialization 및 deserialization을 사용하면 serialize된 문자열에서 필요한 표준 시간대를 복원하여 예기치 않은 TimeZoneNotFoundException을 처리할 수 있으므로 응용 프로그램이 계속 실행됩니다.

다음 예제에서는 사용자 지정 중부 표준시를 만들고 serialize합니다. 그런 다음 레지스트리에서 중부 표준시를 검색합니다. 검색 작업에서 TimeZoneNotFoundException 또는 InvalidTimeZoneException이 throw되는 경우 예외 처리기에서 표준 시간대를 deserialize합니다.

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

Serialize된 문자열 저장 및 필요한 경우 복원

앞의 예제에서는 표준 시간대 정보를 문자열 변수에 저장하고 필요한 경우에 복원했습니다. 그러나 serialize된 표준 시간대 정보가 포함된 문자열 자체는 외부 파일, 응용 프로그램에 포함된 리소스 파일, 레지스트리 등과 같은 저장 미디어에 저장될 수 있습니다. 사용자 지정 표준 시간대에 대한 정보는 레지스트리에 있는 시스템의 표준 시간대 키와 별도로 저장해야 합니다.

또한 이와 같은 방식으로 serialize된 표준 시간대 문자열을 저장하면 표준 시간대 작성 루틴이 응용 프로그램 자체에서 분리됩니다. 예를 들어 응용 프로그램이 사용할 수 있는 기록 표준 시간대 정보가 포함된 데이터 파일을 표준 시간대 작성 루틴에서 실행하고 만들 수 있습니다. 그런 다음 이 데이터 파일을 응용 프로그램에 설치하고 응용 프로그램에 표준 시간대가 필요한 경우 이 데이터 파일을 열어 하나 이상의 표준 시간대를 deserialize할 수 있습니다.

포함 리소스를 사용하여 serialize된 표준 시간대 데이터를 저장하는 예제는 방법: 포함 리소스에 표준 시간대 저장방법: 포함 리소스에서 표준 시간대 복원을 참조하십시오.

참고 항목

기타 리소스

시간 및 표준 시간대