다음을 통해 공유


날짜 및 시간을 사용하여 산술 연산 수행

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

DateTime 값과 비교 및 산술 연산

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

using System;

public enum TimeComparison2
{
    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(TimeComparison2), 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와 현지 시간 간의 차이가 7시간임을 나타냅니다. 그러나 이 두 값은 단일 시점의 다른 표현을 제공하기 때문에 이 경우 시간 간격이 UTC에서 현지 표준 시간대의 오프셋에 완전히 기인한다는 것이 분명합니다.

더 일반적으로, DateTime.Kind 속성은 Kind 비교 및 산술 메서드에서 반환된 결과에 영향을 주지 않지만(두 개의 동일한 시간점 비교를 예로 들 수 있습니다), 이러한 결과의 해석에는 영향을 미칠 수 있습니다. 다음은 그 예입니다.

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

  • 두 날짜 및 시간 값의 DateTime.Kind 속성이 모두 DateTimeKind과 같거나, 다른 DateTime.Kind 속성 값을 가진 두 날짜 및 시간 값에 대해 수행된 산술 또는 비교 연산의 결과는 두 값의 클록 시간 차이를 반영합니다.

  • 현지 날짜 및 시간 값에 대한 산술 또는 비교 작업은 특정 값이 모호하거나 잘못된지 여부를 고려하지 않으며, 현지 표준 시간대의 일광 절약 시간제 전환으로 인한 조정 규칙의 영향을 고려하지 않습니다.

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

  • 지정되지 않은 시간과 UTC 또는 현지 시간의 차이를 비교하거나 계산하는 모든 작업은 간단한 클록 시간을 반영합니다. 표준 시간대 차이는 고려되지 않으며 결과는 표준 시간대 조정 규칙의 적용을 반영하지 않습니다.

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

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

DateTimeOffset 값을 사용하여 비교 및 산술 연산

DateTimeOffset 값에는 날짜 및 시간뿐만 아니라 UTC를 기준으로 해당 날짜와 시간을 명확하게 정의하는 오프셋도 포함됩니다. 이 오프셋을 사용하면 DateTime 값과 다르게 같음을 정의할 수 있습니다. DateTime 값은 날짜 및 시간 값이 같으면 같지만 DateTimeOffset 값은 모두 같은 시점을 참조하는 경우 같습니다. 비교 및 두 날짜와 시간 사이의 간격을 결정하는 대부분의 산술 연산에서 사용되는 경우 DateTimeOffset 값이 더 정확하고 해석이 덜 필요합니다. 다음 예제는 로컬 및 UTC DateTimeOffset 값을 비교한 이전 예제와 동일한 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:00에 발생합니다. 이를 염두에 두고 2008년 3월 9일 오전 1시 30분에 중부 표준 시간대에 2시간 반 간격을 추가하면 2008년 3월 9일 오전 5:00의 날짜와 시간이 생성됩니다. 그러나 다음 예제와 같이 추가 결과는 2008년 3월 9일 오전 4:00입니다. 이 작업의 결과는 올바른 시점을 나타내지만 관심 있는 표준 시간대의 시간(즉, 예상 표준 시간대 오프셋이 없음)은 아닙니다.

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:00에 2시간 반을 추가한 이전 코드와 유사합니다. 그러나 날짜 및 시간 산술 연산을 수행하기 전에 중앙 표준 시간을 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

참고하십시오