다음을 통해 공유


표준 시간대 저장 및 복원

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

  • 애플리케이션에 필요한 표준 시간대는 레지스트리에 정의되지 않았거나 레지스트리에서 이름이 변경되거나 제거되었을 수 있습니다.

  • 레지스트리에 정의된 표준 시간대에는 과거 표준 시간대 변환에 필요한 특정 조정 규칙에 대한 정보가 부족할 수 있습니다.

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

표준 시간대 serialization 및 deserialization

표준 시간대 데이터 직렬화 및 역직렬화를 통한 표준 시간대 저장 및 복원에는 다음 두 가지 메서드 호출만 포함됩니다.

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

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

serialization 및 deserialization 시나리오

나중에 사용할 수 있도록 TimeZoneInfo 개체를 문자열에 저장(또는 직렬화)하고 복원(또는 역직렬화)하는 기능은 TimeZoneInfo 클래스의 유틸리티와 유연성을 모두 향상합니다. 이 섹션에서는 serialization 및 deserialization이 가장 유용한 몇 가지 상황을 살펴봅니다.

애플리케이션에서 표준 시간대 데이터 직렬화 및 역직렬화

필요한 경우 문자열에서 직렬화된 표준 시간대를 복원할 수 있습니다. 레지스트리에서 검색된 표준 시간대가 특정 날짜 범위 내에서 날짜와 시간을 올바르게 변환할 수 없는 경우 애플리케이션에서 이 작업을 수행할 수 있습니다. 예를 들어 Windows XP 레지스트리의 표준 시간대 데이터는 단일 조정 규칙을 지원하지만 Windows Vista 레지스트리에 정의된 표준 시간대는 일반적으로 두 가지 조정 규칙에 대한 정보를 제공합니다. 이는 과거 시간 변환이 정확하지 않을 수 있음을 의미합니다. 표준 시간대 데이터의 serialization 및 deserialization는 이 제한을 처리할 수 있습니다.

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

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

표준 시간대 예외 처리

레지스트리는 동적 구조이므로 해당 콘텐츠는 실수로 또는 의도적으로 수정될 수 있습니다. 즉, 레지스트리에 정의되어야 하고 애플리케이션을 성공적으로 실행하는 데 필요한 표준 시간대가 없을 수 있습니다. 표준 시간대 serialization 및 deserialization을 지원하지 않으면 애플리케이션을 종료하여 결과 TimeZoneNotFoundException(을)를 처리할 수밖에 없습니다. 그러나 표준 시간대 serialization 및 deserialization을 사용하면 직렬화된 문자열에서 필요한 표준 시간대를 복원하여 예기치 않은 TimeZoneNotFoundException 작업을 처리할 수 있으며 애플리케이션은 계속 실행됩니다.

다음 예제에서는 사용자 지정 중앙 표준 시간대를 만들고 직렬화합니다. 그런 다음 레지스트리에서 중앙 표준 시간대를 검색하려고 시도합니다. 검색 작업이 TimeZoneNotFoundException 또는 InvalidTimeZoneException를 throw하는 경우 예외 처리기는 표준 시간대를 역직렬화합니다.

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

직렬화된 문자열 저장 및 필요 시 복원

이전 예제에서는 표준 시간대 정보를 문자열 변수에 저장하고 필요할 때 복원했습니다. 그러나 직렬화된 표준 시간대 정보를 포함하는 문자열 자체는 외부 파일, 애플리케이션에 포함된 리소스 파일 또는 레지스트리와 같은 일부 스토리지 매체에 저장할 수 있습니다. (사용자 지정 표준 시간대에 대한 정보는 레지스트리에 있는 시스템의 표준 시간대 키와 별도로 저장되어야 합니다.)

이러한 방식으로 직렬화된 표준 시간대 문자열을 저장하면 표준 시간대 만들기 루틴이 애플리케이션 자체와 분리됩니다. 예를 들어 표준 시간대 만들기 루틴은 애플리케이션에서 사용할 수 있는 기록 표준 시간대 정보를 포함하는 데이터 파일을 실행하고 만들 수 있습니다. 그런 다음, 애플리케이션과 함께 데이터 파일을 설치할 수 있으며, 열 수 있으며 애플리케이션에 필요할 때 하나 이상의 표준 시간대를 역직렬화할 수 있습니다.

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

참고 항목