다음을 통해 공유


방법: 날짜 및 시간 산술 연산의 표준 시간대 사용

업데이트: 2007년 11월

일반적으로 DateTime 또는 DateTimeOffset 값을 사용하여 날짜 및 시간 연산을 수행할 경우에는 표준 시간대 조정 규칙이 결과에 반영되지 않습니다. 이것은 Kind 속성이 Local로 설정된 경우와 같이 날짜 및 시간 값의 표준 시간대를 명확히 식별할 수 있는 경우에도 적용됩니다. 이 항목에서는 특정 표준 시간대에 속한 날짜 및 시간 값에 대한 산술 연산을 수행하는 방법을 보여 줍니다. 산술 연산의 결과에는 표준 시간대의 조정 규칙이 반영됩니다.

날짜 및 시간 연산에 조정 규칙을 적용하려면

  1. 날짜 및 시간 값을 이 값이 속한 표준 시간대와 밀접하게 결합하는 일부 메서드를 구현합니다. 예를 들어 날짜 및 시간 값과 해당 표준 시간대를 모두 포함하는 구조체를 선언합니다. 다음 예제에서는 이 방법을 사용하여 DateTime 값을 해당 표준 시간대에 연결합니다.

    ' Define a structure for DateTime values for internal use only
    Friend Structure TimeWithTimeZone
       Dim TimeZone As TimeZoneInfo
       Dim Time As Date
    End Structure
    
    // Define a structure for DateTime values for internal use only
    internal struct TimeWithTimeZone
    {
       TimeZoneInfo TimeZone;
       DateTime Time;
    }
    
  2. ConvertTimeToUtc 메서드 또는 ConvertTime 메서드를 호출하여 시간을 UTC(협정 세계시)로 변환합니다.

  3. UTC 시간에 대해 산술 연산을 수행합니다.

  4. TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo) 메서드를 사용하여 시간을 UTC에서 원래 시간과 관련된 표준 시간대로 변환합니다.

예제

다음 예제에서는 중부 표준시 2008년 3월 9일 오전 1시 30분에 2시간 30분을 더합니다. 30분 뒤인 2008년 3월 9일 오전 2시에 표준 시간대가 일광 절약 시간으로 전환됩니다. 이 예제에서는 이전 단원에서 열거한 네 가지 단계를 수행하므로 결과 시간을 2008년 3월 9일 오전 5시로 제대로 보고합니다.

Public Structure TimeZoneTime
   Public TimeZone As TimeZoneInfo
   Public Time As Date

   Public Sub New(tz As TimeZoneInfo, time As Date)
      If tz Is Nothing Then _
         Throw New ArgumentNullException("The time zone cannot be a null reference.")

      Me.TimeZone = tz
      Me.Time = time
   End Sub

   Public Function AddTime(interval As TimeSpan) As TimeZoneTime
      ' Convert time to UTC
      Dim utcTime As DateTime = TimeZoneInfo.ConvertTimeToUtc(Me.Time, _
                                                              Me.TimeZone)      
      ' Add time interval to time
      utcTime = utcTime.Add(interval)
      ' Convert time back to time in time zone
      Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, _
                              TimeZoneInfo.Utc, Me.TimeZone))
   End Function
End Structure

Module TimeArithmetic
   Public Const tzName As String = "Central Standard Time"

   Public Sub Main()
      Try
         Dim cstTime1, cstTime2 As TimeZoneTime

         Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
         Dim time1 As Date = #03/09/2008 1:30AM#
         Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

         cstTime1 = New TimeZoneTime(cst, time1)
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                    twoAndAHalfHours.ToString(), _ 
                                                    cstTime2.Time)  
      Catch
         Console.WriteLine("Unable to find {0}.", tzName)
      End Try   
   End Sub   
End Module
using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTime Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTime time)
   {
      if (tz == null) 
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;   
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(this.Time, this.TimeZone);
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, 
                              TimeZoneInfo.Utc, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);          
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst, time1);
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, 
                                                    twoAndAHalfHours.ToString(),  
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}

DateTimeDateTimeOffset 값은 모두 해당 값이 속할 수 있는 표준 시간대와 분리되어 있습니다. 표준 시간대의 조정 규칙을 자동으로 적용하는 방식으로 날짜 및 시간 연산을 수행하려면 날짜 및 시간 값이 속한 표준 시간대를 즉시 식별할 수 있어야 합니다. 즉, 날짜 및 시간과 관련 표준 시간대가 밀접하게 결합되어 있어야 합니다. 다음과 같은 여러 가지 방법으로 이렇게 할 수 있습니다.

  • 응용 프로그램에서 사용되는 모든 시간이 특정 표준 시간대에 속한다고 가정합니다. 일부 경우에는 적합하지 않지만 이 방법은 제한된 융통성과 이식성을 제공할 수 있습니다.

  • 날짜 및 시간과 관련 표준 시간대를 모두 해당 형식의 필드로 포함하여 밀접하게 결합하는 형식을 정의합니다. 날짜 및 시간과 표준 시간대를 두 개의 멤버 필드에 저장하는 구조체를 정의하는 아래 코드 예제에서 이 방법이 사용됩니다.

이 예제에서는 표준 시간대 조정 규칙이 결과에 적용되도록 DateTime 값에 대한 산술 연산을 수행하는 방법을 보여 줍니다. 그러나 DateTimeOffset 값도 쉽게 사용할 수 있습니다. 따라서 다음 예제에서는 원래 예제의 코드를 변경하여 DateTime 값 대신 DateTimeOffset을 사용하는 방법을 보여 줍니다.

Public Structure TimeZoneTime
   Public TimeZone As TimeZoneInfo
   Public Time As DateTimeOffset

   Public Sub New(tz As TimeZoneInfo, time As DateTimeOffset)
      If tz Is Nothing Then _
         Throw New ArgumentNullException("The time zone cannot be a null reference.")

      Me.TimeZone = tz
      Me.Time = time
   End Sub

   Public Function AddTime(interval As TimeSpan) As TimeZoneTime
      ' Convert time to UTC
      Dim utcTime As DateTimeOffset = TimeZoneInfo.ConvertTime(Me.Time, TimeZoneInfo.Utc)      
      ' Add time interval to time
      utcTime = utcTime.Add(interval)
      ' Convert time back to time in time zone
      Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, Me.TimeZone))
   End Function
End Structure

Module TimeArithmetic
   Public Const tzName As String = "Central Standard Time"

   Public Sub Main()
      Try
         Dim cstTime1, cstTime2 As TimeZoneTime

         Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
         Dim time1 As Date = #03/09/2008 1:30AM#
         Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

         cstTime1 = New TimeZoneTime(cst, _
                        New DateTimeOffset(time1, cst.GetUtcOffset(time1)))
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                    twoAndAHalfHours.ToString(), _ 
                                                    cstTime2.Time)  
      Catch
         Console.WriteLine("Unable to find {0}.", tzName)
      End Try   
   End Sub   
End Module
using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTimeOffset Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTimeOffset time)
   {
      if (tz == null) 
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;   
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTimeOffset utcTime = TimeZoneInfo.ConvertTime(this.Time, TimeZoneInfo.Utc);      
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);          
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst, 
                        new DateTimeOffset(time1, cst.GetUtcOffset(time1)));
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, 
                                                    twoAndAHalfHours.ToString(),  
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}

DateTimeOffset 값을 먼저 UTC로 변환하지 않고 이 값에 대해 이러한 더하기를 간단히 수행하는 경우 결과에는 올바른 시점이 반영되지만 오프셋에는 해당 시간에 대해 지정한 표준 시간대의 오프셋이 반영되지 않습니다.

코드 컴파일

이 예제에는 다음 사항이 필요합니다.

  • System.Core.dll에 대한 참조를 프로젝트에 추가해야 합니다.

  • System 네임스페이스를 using 문을 사용하여 가져와야 합니다(C# 코드인 경우 필요).

참고 항목

개념

날짜 및 시간에 대한 산술 연산 수행

기타 리소스

시간 및 표준 시간대