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

구조와 DateTimeOffset 구조 모두 DateTime 해당 값에 대해 산술 연산을 수행하는 멤버를 제공하지만 산술 연산의 결과는 매우 다릅니다. 이 문서는 이러한 차이점을 검사하고 날짜 및 시간 데이터에서 표준 시간대 인식 수준에 연결하며 날짜 및 시간 데이터를 사용하여 표준 시간대 인식 작업을 완벽하게 수행하는 방법에 대해 설명합니다.

DateTime 값과 비교 및 산술 연산

DateTime.Kind 속성을 사용하면 DateTimeKind 현지 시간, UTC(협정 세계시) 또는 지정되지 않은 표준 시간대의 시간을 나타내는지 여부를 나타내는 날짜 및 시간에 값을 할당할 수 있습니다. 그러나 이 제한된 표준 시간대 정보는 값에 대한 DateTimeKind 날짜 및 시간 산술 연산을 비교하거나 수행할 때 무시됩니다. 다음 예제에서는 현재 현지 시간을 현재 UTC 시간과 비교하여 표준 시간대 정보가 무시되는 방법을 보여 줍니다.

using System;

public enum TimeComparison
{
   EarlierThan = -1,
   TheSameAs = 0,
   LaterThan = 1
}

public class DateManipulation
{
   public static void Main()
   {
      DateTime localTime = DateTime.Now;
      DateTime utcTime = DateTime.UtcNow;

      Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours",
                        localTime.Kind,
                        utcTime.Kind,
                        (localTime - utcTime).Hours,
                        (localTime - utcTime).Minutes);
      Console.WriteLine("The {0} time is {1} the {2} time.",
                        localTime.Kind,
                        Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)),
                        utcTime.Kind);
   }
}
// If run in the U.S. Pacific Standard Time zone, the example displays
// the following output to the console:
//    Difference between Local and Utc time: -7:0 hours
//    The Local time is EarlierThan the Utc time.
Public Enum TimeComparison As Integer
    EarlierThan = -1
    TheSameAs = 0
    LaterThan = 1
End Enum

Module DateManipulation
    Public Sub Main()
        Dim localTime As Date = Date.Now
        Dim utcTime As Date = Date.UtcNow

        Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours", _
                          localTime.Kind.ToString(), _
                          utcTime.Kind.ToString(), _
                          (localTime - utcTime).Hours, _
                          (localTime - utcTime).Minutes)
        Console.WriteLine("The {0} time is {1} the {2} time.", _
                          localTime.Kind.ToString(), _
                          [Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)), _
                          utcTime.Kind.ToString())
        ' If run in the U.S. Pacific Standard Time zone, the example displays 
        ' the following output to the console:
        '    Difference between Local and Utc time: -7:0 hours
        '    The Local time is EarlierThan the Utc time.                                                    
    End Sub
End Module

CompareTo(DateTime) 메서드는 현지 시간이 UTC 시간보다 빠르거나 느리다고 보고하고, 빼기 연산은 미국 태평양 표준 시간대에 있는 시스템의 UTC와 현지 시간 간 차이가 일곱 시간임을 나타냅니다. 그러나 이 두 값은 단일 시점의 서로 다른 표현을 제공하기 때문에 이 경우 시간 간격이 UTC에서 현지 표준 시간대의 오프셋에 완전히 기인한다는 것이 분명합니다.

더 일반적으로 DateTime.Kind 속성은 비교 및 산술 메서드에 의해 반환된 Kind 결과에 영향을 주지 않습니다(동일한 두 시점의 비교에서 알 수 있음). 이러한 결과의 해석에 영향을 줄 수 있습니다. 예:

  • 속성이 같은 DateTimeKind 두 날짜 및 시간 값에 대해 수행된 모든 산술 연산의 결과는 두 값 DateTime.Kind 사이의 실제 시간 간격을 반영합니다. 마찬가지로 이러한 두 개의 날짜 및 시간 값을 비교하면 시간 간의 관계를 정확하게 반영합니다.

  • 속성 값이 서로 다른 DateTime.Kind 두 날짜 및 시간 값의 속성이 DateTime.Kind 같은 DateTimeKind 두 날짜 및 시간 값에 대해 수행된 산술 또는 비교 작업의 결과는 두 값 간의 클록 시간 차이를 반영합니다.

  • 로컬 날짜 및 시간 값에 대한 산술 또는 비교 작업은 특정 값이 모호하거나 잘못되었는지 여부를 고려하지 않거나 현지 표준 시간대 전환 또는 일광 절약 시간에서 발생하는 모든 조정 규칙의 효과를 고려하지 않습니다.

  • UTC와 현지 시간 사이의 차이를 비교하거나 계산하는 작업에는 결과에 있는 UTC에서 현지 표준 시간대 오프셋과 동일한 시간 간격이 포함됩니다.

  • 지정되지 않은 시간과 UTC 또는 현지 시간 사이의 차이를 비교하거나 계산하는 작업은 간단한 클록 시간을 반영합니다. 표준 시간대 차이를 고려하지 않으면 결과가 표준 시간대 조정 규칙의 애플리케이션을 반영하지 않습니다.

  • 두 개의 지정되지 않은 시간 사이의 차이를 비교하거나 계산하는 작업에는 두 개의 다른 시간대의 시간 사이의 차이를 반영하는 알 수 없는 간격이 포함될 수 있습니다.

표준 시간대 차이가 날짜 및 시간 계산에 영향을 미치지 않는 많은 시나리오(이러한 시나리오 중 일부에 대한 설명은 DateTime, DateTimeOffset, TimeSpan 및 TimeZoneInfo 중에서 선택 참조) 또는 날짜 및 시간 데이터의 컨텍스트가 비교 또는 산술 연산의 의미를 정의하는 많은 시나리오가 있습니다.

DateTimeOffset 값과 비교 및 산술 연산

DateTimeOffset 값에는 날짜 및 시간뿐만 아니라 UTC를 기준으로 해당 날짜와 시간을 명확하게 정의하는 오프셋도 포함됩니다. 이 오프셋을 사용하면 값과 다르게 같음을 DateTime 정의할 수 있습니다. DateTime 값은 날짜 및 시간 값이 같으면 같지만 두 DateTimeOffset 값이 모두 같은 시점을 참조하면 값이 같습니다. 비교 및 두 날짜와 시간 DateTimeOffset 사이의 간격을 결정하는 대부분의 산술 연산에서 사용되는 경우 값이 더 정확하고 해석이 덜 필요합니다. 다음 예제는 DateTimeOffset 로컬 값과 UTC DateTimeOffset 값을 비교한 이전 예제와 동일한 동작의 차이를 보여 줍니다.

using System;

public enum TimeComparison
{
   EarlierThan = -1,
   TheSameAs = 0,
   LaterThan = 1
}

public class DateTimeOffsetManipulation
{
   public static void Main()
   {
      DateTimeOffset localTime = DateTimeOffset.Now;
      DateTimeOffset utcTime = DateTimeOffset.UtcNow;

      Console.WriteLine("Difference between local time and UTC: {0}:{1:D2} hours",
                        (localTime - utcTime).Hours,
                        (localTime - utcTime).Minutes);
      Console.WriteLine("The local time is {0} UTC.",
                        Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)));
   }
}
// Regardless of the local time zone, the example displays
// the following output to the console:
//    Difference between local time and UTC: 0:00 hours.
//    The local time is TheSameAs UTC.
Public Enum TimeComparison As Integer
    EarlierThan = -1
    TheSameAs = 0
    LaterThan = 1
End Enum

Module DateTimeOffsetManipulation
    Public Sub Main()
        Dim localTime As DateTimeOffset = DateTimeOffset.Now
        Dim utcTime As DateTimeOffset = DateTimeOffset.UtcNow

        Console.WriteLine("Difference between local time and UTC: {0}:{1:D2} hours.", _
                          (localTime - utcTime).Hours, _
                          (localTime - utcTime).Minutes)
        Console.WriteLine("The local time is {0} UTC.", _
                          [Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)))
    End Sub
End Module
' Regardless of the local time zone, the example displays 
' the following output to the console:
'    Difference between local time and UTC: 0:00 hours.
'    The local time is TheSameAs UTC.
'          Console.WriteLine(e.GetType().Name)

이 예제에서 메서드는 CompareTo 현재 현지 시간과 현재 UTC 시간이 동일하다는 것을 나타내고 값을 빼 CompareTo(DateTimeOffset) 면 두 시간의 TimeSpan.Zero차이가 있음을 나타냅니다.

날짜 및 시간 산술 연산에서 값을 사용하는 DateTimeOffset 주요 제한 사항은 DateTimeOffset 값에 표준 시간대 인식이 있지만 표준 시간대를 완전히 인식하지는 않는다는 것입니다. 변수에 값이 DateTimeOffset 처음 할당될 때 DateTimeOffset 값의 오프셋은 UTC에서 표준 시간대의 오프셋을 반영하지만 이후 표준 시간대에서 연결이 해제됩니다. 더 이상 식별 가능한 시간과 직접 연결되어 있기 때문에 날짜 및 시간 간격의 더하기 및 빼기는 표준 시간대의 조정 규칙을 고려하지 않습니다.

예를 들어 미국 중부 표준시에서는 2008년 3월 9일 오전 2시에 표준 시간대가 일광 절약 시간제로 전환됩니다. 이를 염두에 두고 2008년 3월 9일 오전 1시 30분에 중앙 표준 시간에 2시간 반 간격을 추가하면 2008년 3월 9일 오전 5:00의 날짜와 시간이 생성됩니다. 그러나 다음 예제와 같이 이 더하기 연산의 결과는 2008년 3월 9일 오전 4시가 됩니다. 이 작업의 결과는 올바른 시점을 나타내지만 관심 있는 표준 시간대의 시간(즉, 예상 표준 시간대 오프셋이 없음)은 아닙니다.

using System;

public class IntervalArithmetic
{
   public static void Main()
   {
      DateTime generalTime = new DateTime(2008, 3, 9, 1, 30, 0);
      const string tzName = "Central Standard Time";
      TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

      // Instantiate DateTimeOffset value to have correct CST offset
      try
      {
         DateTimeOffset centralTime1 = new DateTimeOffset(generalTime,
                    TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime));

         // Add two and a half hours
         DateTimeOffset centralTime2 = centralTime1.Add(twoAndAHalfHours);
         // Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1,
                                                    twoAndAHalfHours.ToString(),
                                                    centralTime2);
      }
      catch (TimeZoneNotFoundException)
      {
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
      }
   }
}
// The example displays the following output to the console:
//    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00
Module IntervalArithmetic
    Public Sub Main()
        Dim generalTime As Date = #03/09/2008 1:30AM#
        Const tzName As String = "Central Standard Time"
        Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

        ' Instantiate DateTimeOffset value to have correct CST offset
        Try
            Dim centralTime1 As New DateTimeOffset(generalTime, _
                       TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime))

            ' Add two and a half hours      
            Dim centralTime2 As DateTimeOffset = centralTime1.Add(twoAndAHalfHours)
            ' Display result
            Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
                                                       twoAndAHalfHours.ToString(), _
                                                       centralTime2)
        Catch e As TimeZoneNotFoundException
            Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
        End Try
    End Sub
End Module
' The example displays the following output to the console:
'    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00

표준 시간대의 시간이 있는 산술 연산

클래스에는 TimeZoneInfo 한 표준 시간대에서 다른 표준 시간대로 시간을 변환할 때 조정을 자동으로 적용하는 변환 메서드가 포함됩니다. 이러한 변환 방법은 다음과 같습니다.

자세한 내용은 표준 시간대 간 시간 변환을 참조하세요.

이 클래스는 TimeZoneInfo 날짜 및 시간 산술 연산을 수행할 때 조정 규칙을 자동으로 적용하는 메서드를 제공하지 않습니다. 그러나 표준 시간대의 시간을 UTC로 변환하고 산술 연산을 수행한 다음 UTC에서 표준 시간대의 시간으로 다시 변환하여 조정 규칙을 적용할 수 있습니다. 자세한 내용은 방법: 날짜 및 시간 산술의 표준 시간대 사용 방법을 참조하세요.

예를 들어 다음 코드는 2008년 3월 9일 오전 2시에 2시간 30분을 더하는 이전 코드와 비슷합니다. 그러나 날짜 및 시간 산술 연산을 수행하기 전에 중부 표준시를 UTC로 변환한 다음 UTC의 결과를 중부 표준시로 다시 변환하기 때문에 결과 시간은 일광 절약 시간제로 전환된 중앙 표준 시간대를 반영합니다.

using System;

public class TimeZoneAwareArithmetic
{
   public static void Main()
   {
      const string tzName = "Central Standard Time";

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

      // Instantiate DateTimeOffset value to have correct CST offset
      try
      {
         DateTimeOffset centralTime1 = new DateTimeOffset(generalTime,
                                       cst.GetUtcOffset(generalTime));

         // Add two and a half hours
         DateTimeOffset utcTime = centralTime1.ToUniversalTime();
         utcTime += twoAndAHalfHours;

         DateTimeOffset centralTime2 = TimeZoneInfo.ConvertTime(utcTime, cst);
         // Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1,
                                                    twoAndAHalfHours.ToString(),
                                                    centralTime2);
      }
      catch (TimeZoneNotFoundException)
      {
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
      }
   }
}
// The example displays the following output to the console:
//    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00
Module TimeZoneAwareArithmetic
    Public Sub Main()
        Const tzName As String = "Central Standard Time"

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

        ' Instantiate DateTimeOffset value to have correct CST offset
        Try
            Dim centralTime1 As New DateTimeOffset(generalTime, _
                       cst.GetUtcOffset(generalTime))

            ' Add two and a half hours 
            Dim utcTime As DateTimeOffset = centralTime1.ToUniversalTime()
            utcTime += twoAndAHalfHours

            Dim centralTime2 As DateTimeOffset = TimeZoneInfo.ConvertTime(utcTime, cst)
            ' Display result
            Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
                                                       twoAndAHalfHours.ToString(), _
                                                       centralTime2)
        Catch e As TimeZoneNotFoundException
            Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
        End Try
    End Sub
End Module
' The example displays the following output to the console:
'    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00

참고 항목