다음을 통해 공유


표준 시간대 간 시간 변환

날짜 및 시간을 사용하는 모든 애플리케이션에서 표준 시간대 간의 차이를 처리하는 것이 점점 더 중요해지고 있습니다. 애플리케이션은 더 이상 모든 시간을 DateTime 구조에서 제공되는 현지 시간으로 표현할 수 있다고 가정할 수 없습니다. 예를 들어 미국 동부 지역의 현재 시간을 표시하는 웹 페이지는 동아시아의 고객에 대한 신뢰성이 부족합니다. 이 문서에서는 시간대 간 시간 변환과 시간대 인식이 제한된 DateTimeOffset 값을 변환하는 방법을 설명합니다.

협정 세계시로 변환

UTC(협정 세계시)는 정밀도가 높은 원자성 시간 표준입니다. 전 세계의 표준 시간대는 UTC의 양수 또는 음수 오프셋으로 표현됩니다. 따라서 UTC는 시간대에 구애받지 않거나 시간대에 중립적인 시간을 제공합니다. 컴퓨터에서 날짜 및 시간의 이식성이 중요한 경우 UTC를 사용하는 것이 좋습니다. 날짜 및 시간을 사용하는 세부 정보 및 기타 모범 사례는 .NET Framework에서 DateTime을 사용하는 코딩 모범 사례를 참조하세요. 개별 표준 시간대를 UTC로 변환하면 시간을 쉽게 비교할 수 있습니다.

비고

단일 시점을 DateTimeOffset 명확하게 나타내도록 구조체를 직렬화할 수도 있습니다. DateTimeOffset 개체는 UTC의 오프셋과 함께 날짜 및 시간 값을 저장하므로 항상 UTC와 관련하여 특정 시점을 나타냅니다.

시간을 UTC로 변환하는 가장 쉬운 방법은 (staticVisual Basic에서) Shared 메서드를 TimeZoneInfo.ConvertTimeToUtc(DateTime) 호출하는 것입니다. 메서드에서 수행하는 정확한 변환은 다음 표와 같이 매개 변수 속성의 dateTimeKind 에 따라 달라집니다.

DateTime.Kind 변환
DateTimeKind.Local 현지 시간을 UTC로 변환합니다.
DateTimeKind.Unspecified 매개 변수가 dateTime 현지 시간이라고 가정하고 현지 시간을 UTC로 변환합니다.
DateTimeKind.Utc 변경되지 않은 매개 변수를 dateTime 반환합니다.

다음 코드는 현재 현지 시간을 UTC로 변환하고 결과를 콘솔에 표시합니다.

DateTime dateNow = DateTime.Now;
Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(dateNow)} UTC.");
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
                  TimeZoneInfo.ConvertTimeToUtc(dateNow))

날짜 및 시간 값이 현지 시간 또는 UTC를 나타내지 않으면 메서드가 ToUniversalTime 잘못된 결과를 반환할 가능성이 높습니다. 그러나 이 메서드를 TimeZoneInfo.ConvertTimeToUtc 사용하여 지정된 표준 시간대에서 날짜와 시간을 변환할 수 있습니다. 대상 표준 시간대를 나타내는 개체를 검색하는 TimeZoneInfo 방법은 로컬 시스템에 정의된 표준 시간대 찾기를 참조하세요. 다음 코드에서는 이 메서드를 TimeZoneInfo.ConvertTimeToUtc 사용하여 동부 표준시를 UTC로 변환합니다.

DateTime easternTime = new DateTime(2007, 01, 02, 12, 16, 00);
string easternZoneId = "Eastern Standard Time";
try
{
    TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
    Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)} UTC.");
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine($"Unable to find the {easternZoneId} zone in the registry.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine($"Registry data on the {easternZoneId} zone has been corrupted.");
}
Dim easternTime As New Date(2007, 01, 02, 12, 16, 00)
Dim easternZoneId As String = "Eastern Standard Time"
Try
    Dim easternZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId)
    Console.WriteLine("The date and time are {0} UTC.", _
                      TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("Unable to find the {0} zone in the registry.", _
                      easternZoneId)
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the {0} zone has been corrupted.", _
                      easternZoneId)
End Try

TimeZoneInfo.ConvertTimeToUtc 메서드는 TimeZoneInfo.ConvertTimeToUtc 개체의 DateTime 속성과 표준 시간대가 일치하지 않으면 Kind을(를) 던집니다. Kind 속성이 DateTimeKind.Local이지만 TimeZoneInfo 개체가 현지 표준 시간대를 나타내지 않거나, Kind 속성이 DateTimeKind.Utc인데 TimeZoneInfo 개체가 TimeZoneInfo.Utc가 아닌 경우 불일치가 발생합니다.

모든 이러한 메서드는 DateTime 값을 매개변수로 받아 DateTime 값을 반환합니다. 값의 경우, DateTimeOffset 구조체에는 현재 인스턴스의 날짜와 시간을 UTC로 변환하는 DateTimeOffset 인스턴스 메서드가 있습니다. 다음 예제에서는 메서드를 ToUniversalTime 호출하여 현지 시간을 여러 번 UTC로 변환합니다.

DateTimeOffset localTime, otherTime, universalTime;

// Define local time in local time zone
localTime = new DateTimeOffset(new DateTime(2007, 6, 15, 12, 0, 0));
Console.WriteLine($"Local time: {localTime}");
Console.WriteLine();

// Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero);
Console.WriteLine($"Other time: {otherTime}");
Console.WriteLine($"{localTime} = {otherTime}: {localTime.Equals(otherTime)}");
Console.WriteLine($"{localTime} exactly equals {otherTime}: {localTime.EqualsExact(otherTime)}");
Console.WriteLine();

// Convert other time to UTC
universalTime = localTime.ToUniversalTime();
Console.WriteLine($"Universal time: {universalTime}");
Console.WriteLine($"{otherTime} = {universalTime}: {universalTime.Equals(otherTime)}");
Console.WriteLine($"{otherTime} exactly equals {universalTime}: {universalTime.EqualsExact(otherTime)}");
Console.WriteLine();

// The example produces the following output to the console:
//    Local time: 6/15/2007 12:00:00 PM -07:00
//
//    Other time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
//
//    Universal time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True
Dim localTime, otherTime, universalTime As DateTimeOffset

' Define local time in local time zone
localTime = New DateTimeOffset(#6/15/2007 12:00:00PM#)
Console.WriteLine("Local time: {0}", localTime)
Console.WriteLine()

' Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero)
Console.WriteLine("Other time: {0}", otherTime)
Console.WriteLine("{0} = {1}: {2}", _
                  localTime, otherTime, _
                  localTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  localTime, otherTime, _
                  localTime.EqualsExact(otherTime))
Console.WriteLine()

' Convert other time to UTC
universalTime = localTime.ToUniversalTime()
Console.WriteLine("Universal time: {0}", universalTime)
Console.WriteLine("{0} = {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.EqualsExact(otherTime))
Console.WriteLine()
' The example produces the following output to the console:
'    Local time: 6/15/2007 12:00:00 PM -07:00
'    
'    Other time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
'    
'    Universal time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True   

UTC를 지정된 표준 시간대로 변환

UTC를 현지 시간으로 변환하려면 다음 UTC를 현지 시간으로 변환 섹션을 참조하세요. UTC를 지정한 표준 시간대의 시간으로 변환하려면 메서드를 호출합니다 ConvertTimeFromUtc . 이 메서드는 다음 두 개의 매개 변수를 사용합니다.

  • 변환할 UTC입니다. 이 값의 DateTime 속성은 Kind 또는 Unspecified로 설정되어야 합니다.

  • UTC를 변환할 대상 시간대입니다.

다음 코드는 UTC를 중앙 표준시로 변환합니다.

DateTime timeUtc = DateTime.UtcNow;
try
{
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    Console.WriteLine("The date and time are {0} {1}.",
                      cstTime,
                      cstZone.IsDaylightSavingTime(cstTime) ?
                              cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Central Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.");
}
Dim timeUtc As Date = Date.UtcNow
Try
    Dim cstZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
    Dim cstTime As Date = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone)
    Console.WriteLine("The date and time are {0} {1}.", _
                      cstTime, _
                      IIf(cstZone.IsDaylightSavingTime(cstTime), _
                          cstZone.DaylightName, cstZone.StandardName))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Central Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.")
End Try

UTC를 현지 시간으로 변환

UTC를 현지 시간으로 변환하려면 변환할 시간을 가진 개체의 ToLocalTime 메서드를 호출 DateTime 합니다. 메서드의 정확한 동작은 다음 표와 같이 개체 Kind 의 속성 값에 따라 달라집니다.

DateTime.Kind 변환
DateTimeKind.Local DateTime 변경되지 않은 값을 반환합니다.
DateTimeKind.Unspecified 값이 DateTime UTC이고 UTC를 현지 시간으로 변환한다고 가정합니다.
DateTimeKind.Utc 값을 현지 시간으로 변환합니다 DateTime .

비고

TimeZone.ToLocalTime 메서드는 DateTime.ToLocalTime 메서드와 동일하게 동작합니다. 변환하려면 날짜 및 시간 값인 단일 매개 변수가 필요합니다.

(staticVisual Basic에서) Shared 메서드를 사용하여 지정된 표준 시간대의 TimeZoneInfo.ConvertTime 시간을 현지 시간으로 변환할 수도 있습니다. 이 기술은 다음 섹션에서 설명합니다.

두 표준 시간대 간 변환

클래스의 다음 두 가지 static(Shared는 Visual Basic에서) 메서드를 사용하여 어떤 두 표준 시간대 간에도 변환할 수 있습니다.

  • ConvertTime

    이 메서드의 매개 변수는 변환할 날짜 및 시간 값, TimeZoneInfo 날짜 및 시간 값의 표준 시간대를 나타내는 개체 및 날짜 및 TimeZoneInfo 시간 값을 변환할 표준 시간대를 나타내는 개체입니다.

  • ConvertTimeBySystemTimeZoneId

    이 메서드의 매개 변수는 변환할 날짜 및 시간 값, 날짜 및 시간 값의 표준 시간대 식별자 및 날짜 및 시간 값을 변환할 표준 시간대의 식별자입니다.

두 메서드 Kind 모두 변환할 날짜 및 시간 값의 속성과 TimeZoneInfo 해당 표준 시간대를 나타내는 개체 또는 표준 시간대 식별자가 서로 일치해야 합니다. 그렇지 않으면 ArgumentException가 던져집니다. 예를 들어 날짜 및 시간 값의 Kind 속성이 DateTimeKind.Local인 경우, 메서드에 매개 변수로 전달된 TimeZoneInfo 객체가 TimeZoneInfo.Local와 같지 않으면 예외가 발생합니다. 메서드에 매개 변수로 전달된 식별자가 TimeZoneInfo.Local.Id와 같지 않으면 예외가 throw됩니다.

다음 예제에서는 이 메서드를 ConvertTime 사용하여 하와이 표준시에서 현지 시간으로 변환합니다.

DateTime hwTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
    TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time");
    Console.WriteLine("{0} {1} is {2} local time.",
            hwTime,
            hwZone.IsDaylightSavingTime(hwTime) ? hwZone.DaylightName : hwZone.StandardName,
            TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local));
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.");
}
Dim hwTime As Date = #2/01/2007 8:00:00 AM#
Try
    Dim hwZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time")
    Console.WriteLine("{0} {1} is {2} local time.", _
                      hwTime, _
                      IIf(hwZone.IsDaylightSavingTime(hwTime), hwZone.DaylightName, hwZone.StandardName), _
                      TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.")
End Try

DateTimeOffset 값 변환

개체가 DateTimeOffset 인스턴스화될 때 해당 표준 시간대에서 연결이 해제되므로 개체가 나타내는 날짜 및 시간 값은 완전히 표준 시간대를 인식하지 못합니다. 그러나 대부분의 경우 애플리케이션은 특정 표준 시간대가 아닌 UTC에서 두 개의 서로 다른 오프셋을 기반으로 날짜와 시간을 변환하기만 하면 됩니다. 이 변환을 수행하려면 현재 인스턴스의 ToOffset 메서드를 호출할 수 있습니다. 메서드의 단일 매개 변수는 메서드가 반환할 새 날짜 및 시간 값의 오프셋입니다.

예를 들어 웹 페이지에 대한 사용자 요청의 날짜 및 시간이 알려져 있고 MM/dd/yyyy hh:mm:ss zzzz 형식의 문자열로 serialize되는 경우 다음 메서드는 ReturnTimeOnServer 이 날짜 및 시간 값을 웹 서버의 날짜 및 시간으로 변환합니다.

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";
   TimeSpan serverOffset = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now);

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = clientTime.ToOffset(serverOffset);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"
    Dim serverOffset As TimeSpan = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now)

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = clientTime.ToOffset(serverOffset)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

메서드가 UTC보다 5시간 이전 표준 시간대의 날짜 및 시간을 나타내는 "9/1/2007 5:32:07 -05:00" 문자열을 전달하는 경우 미국 태평양 표준 시간대에 있는 서버에 대해 "9/1/2007 오전 3:32:07"을 반환합니다.

또한 TimeZoneInfo 클래스에는 TimeZoneInfo 값을 사용하여 시간대 변환을 수행하는 ToOffset(TimeSpan) 메서드의 오버로드도 포함됩니다. 메서드의 매개 변수는 DateTimeOffset 값과 시간대를 참조하여 시간을 변환하는 데 사용됩니다. 메서드 호출은 값을 반환합니다 DateTimeOffset . 예를 들어 이전 예제의 ReturnTimeOnServer 메서드를 다음과 같이 다시 작성하여 메서드를 호출 ConvertTime(DateTimeOffset, TimeZoneInfo) 할 수 있습니다.

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format,
                                  CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = TimeZoneInfo.ConvertTime(clientTime,
                                  TimeZoneInfo.Local);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = TimeZoneInfo.ConvertTime(clientTime, TimeZoneInfo.Local)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

참고하십시오