다음을 통해 공유


방법: 날짜 및 시간 값 라운드트립

업데이트: 2007년 11월

대부분의 응용 프로그램에서 날짜 및 시간 값은 특정 시점을 명확하게 식별합니다. 이 항목에서는 복원된 값이 저장된 값과 같은 시간을 식별하도록 DateTime 값, DateTimeOffset 값 및 날짜/시간 값을 표준 시간대 정보와 함께 저장 및 복원하는 방법을 보여 줍니다.

DateTime 값을 라운드트립하려면

  1. "o" 형식 지정자와 함께 DateTime.ToString(String) 메서드를 호출하여 DateTime 값을 해당 문자열 표현으로 변환합니다.

  2. DateTime 값에 대한 문자열 표현을 파일에 저장하거나 프로세스, 응용 프로그램 도메인 또는 시스템 경계로 전달합니다.

  3. DateTime 값을 나타내는 문자열을 검색합니다.

  4. DateTime.Parse(String, IFormatProvider, DateTimeStyles) 메서드를 호출한 다음 DateTimeStyles.RoundtripKind를 styles 매개 변수의 값으로 전달합니다.

다음 예제에서는 DateTime 값을 라운드트립하는 방법을 보여 줍니다.

Const fileName As String = ".\DateFile.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As Date = DateTime.SpecifyKind(#06/12/2008 6:45:15 PM#, _
                                              DateTimeKind.Local)
Dim dateString As String = dateToSave.ToString("o")      
Console.WriteLine("Converted {0} ({1}) to {2}.", dateToSave.ToString(), _
                  dateToSave.Kind.ToString(), dateString)      
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()   

' Restore DateTime value.
Dim restoredDate As Date

Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDate = DateTime.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} ({2}) from {1}.", restoredDate.ToString(), _
                  fileName, restoredDAte.Kind.ToString())
' The example displays the following output:
'    Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
'    Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
'    Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.
const string fileName = @".\DateFile.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTime dateToSave = DateTime.SpecifyKind(new DateTime(2008, 6, 12, 18, 45, 15), 
                                           DateTimeKind.Local);
string dateString = dateToSave.ToString("o");      
Console.WriteLine("Converted {0} ({1}) to {2}.", 
                  dateToSave.ToString(), 
                  dateToSave.Kind.ToString(), 
                  dateString);      
outFile.WriteLine(dateString);
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName);
outFile.Close();

// Restore DateTime value.
DateTime restoredDate;

StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();
inFile.Close();
restoredDate = DateTime.Parse(dateString, null, DateTimeStyles.RoundtripKind);
Console.WriteLine("Read {0} ({2}) from {1}.", restoredDate.ToString(), 
                                              fileName, 
                                              restoredDate.Kind.ToString());
// The example displays the following output:
//    Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
//    Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
//    Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.

이 방법으로 DateTime 값을 라운드트립하면 모든 현지 시간 및 UTC 시간 값이 유지됩니다. 예를 들어, 미국 태평양 표준 시간대에 있는 시스템에 현지 DateTime 값을 저장한 후 미국 중부 표준 시간대에 있는 시스템에서 값을 복원하면 두 표준 시간대 간의 차이를 반영하여 복원된 날짜 및 시간은 원래 시간보다 2시간 늦은 시간으로 나타납니다. 하지만 지정되지 않은 시간을 이 방법으로 라운드트립하면 결과가 정확하지 않을 수도 있습니다. Kind 속성이 UnspecifiedDateTime 값은 모두 현지 시간으로 처리됩니다. 그렇지 않으면 DateTime이 올바른 시점을 식별하지 못합니다. 이 문제를 해결하려면 날짜 및 시간 값을 해당 표준 시간대와 함께 저장 및 복원합니다.

DateTimeOffset 값을 라운드트립하려면

  1. "o" 형식 지정자와 함께 DateTimeOffset.ToString(String) 메서드를 호출하여 DateTimeOffset 값을 해당 문자열 표현으로 변환합니다.

  2. DateTimeOffset 값에 대한 문자열 표현을 파일에 저장하거나 프로세스, 응용 프로그램 도메인 또는 시스템 경계로 전달합니다.

  3. DateTimeOffset 값을 나타내는 문자열을 검색합니다.

  4. DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) 메서드를 호출한 다음 DateTimeStyles.RoundtripKind를 styles 매개 변수의 값으로 전달합니다.

다음 예제에서는 DateTimeOffset 값을 라운드트립하는 방법을 보여 줍니다.

Const fileName As String = ".\DateOff.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As New DateTimeOffset(2008, 6, 12, 18, 45, 15, _
                                     New TimeSpan(7, 0, 0))
Dim dateString As String = dateToSave.ToString("o")      
Console.WriteLine("Converted {0} to {1}.", dateToSave.ToString(), dateString)      
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()   

' Restore DateTime value.
Dim restoredDateOff As DateTimeOffset

Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDateOff = DateTimeOffset.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} from {1}.", restoredDateOff.ToString(), fileName)
' The example displays the following output:
'    Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
'    Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
'    Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.
const string fileName = @".\DateOff.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTimeOffset dateToSave = new DateTimeOffset(2008, 6, 12, 18, 45, 15, 
                                               new TimeSpan(7, 0, 0));
string dateString = dateToSave.ToString("o");      
Console.WriteLine("Converted {0} to {1}.", dateToSave.ToString(), 
                  dateString);      
outFile.WriteLine(dateString);
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName);
outFile.Close();

// Restore DateTime value.
DateTimeOffset restoredDateOff;

StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();
inFile.Close();
restoredDateOff = DateTimeOffset.Parse(dateString, null, 
                                       DateTimeStyles.RoundtripKind);
Console.WriteLine("Read {0} from {1}.", restoredDateOff.ToString(), 
                  fileName);
// The example displays the following output:
//    Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
//    Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
//    Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.

이 방법으로 라운드트립하면 DateTimeOffset 값이 항상 특정 시점으로 명확하게 식별됩니다. 그런 다음 DateTimeOffset.ToUniversalTime 메서드를 호출하여 값을 UTC(협정 세계시)로 변환하거나 DateTimeOffset.ToOffset 또는 TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) 메서드를 호출하여 값을 특정 표준 시간대의 시간으로 변환할 수 있습니다. 이 방법을 사용할 경우 특정 표준 시간대의 시간을 나타내는 DateTimeOffset 값에 대해 날짜 및 시간 산술 연산을 수행하면 해당 표준 시간대에 대해 정확한 결과가 생성되지 않을 수도 있습니다. 이는 DateTimeOffset 값이 인스턴스화될 때 해당 표준 시간대에서 분리되기 때문입니다. 따라서 날짜 및 시간을 계산할 때 해당 표준 시간대의 조정 규칙이 더 이상 적용되지 않습니다. 날짜 및 시간 값과 해당 표준 시간대가 모두 포함된 사용자 지정 형식을 정의하면 이 문제를 해결할 수 있습니다.

표준 시간대와 함께 날짜 및 시간 값을 라운드트립하려면

  1. 두 개의 필드가 있는 클래스나 구조체를 정의합니다. 첫 번째 필드는 DateTime 또는 DateTimeOffset 개체이고 두 번째 필드는 TimeZoneInfo 개체입니다. 다음 예제는 이 형식의 간단한 버전입니다.

    <Serializable> Public Class DateInTimeZone
       Private tz As TimeZoneInfo
       Private thisDate As DateTimeOffset
    
       Public Sub New()
       End Sub
    
       Public Sub New(date1 As DateTimeOffset, timeZone As TimeZoneInfo)
          If timeZone Is Nothing Then 
             Throw New ArgumentNullException("The time zone cannot be null.")
          End If
          Me.thisDate = date1
          Me.tz = timeZone
       End Sub
    
       Public Property DateAndTime As DateTimeOffset
          Get
             Return Me.thisDate
          End Get
          Set
             If Value.Offset <> Me.tz.GetUtcOffset(Value) Then
                Me.thisDate = TimeZoneInfo.ConvertTime(Value, tz)
             Else
                Me.thisDate = Value
             End If
          End Set
       End Property
    
       Public ReadOnly Property TimeZone As TimeZoneInfo
          Get
             Return tz
          End Get
       End Property
    End Class
    
    [Serializable] public class DateInTimeZone
    {
       private TimeZoneInfo tz;
       private DateTimeOffset thisDate;
    
       public DateInTimeZone() {}
    
       public DateInTimeZone(DateTimeOffset date, TimeZoneInfo timeZone)
       {
          if (timeZone == null) 
             throw new ArgumentNullException("The time zone cannot be null.");
    
          this.thisDate = date;
          this.tz = timeZone;
       }
    
       public DateTimeOffset DateAndTime
       {
          get { 
             return this.thisDate;
          }
          set {
             if (value.Offset != this.tz.GetUtcOffset(value)) 
                this.thisDate = TimeZoneInfo.ConvertTime(value, tz);
             else
                this.thisDate = value;
          }
       }
    
       public TimeZoneInfo TimeZone
       {
          get {
             return this.tz;
          }
       }
    }
    
  2. 클래스를 SerializableAttribute 특성으로 표시합니다.

  3. BinaryFormatter.Serialize 메서드를 사용하여 개체를 serialize합니다.

  4. Deserialize 메서드를 사용하여 개체를 복원합니다.

  5. deserialize된 개체를 올바른 형식의 개체로 캐스팅하거나(C#의 경우) 변환합니다(Visual Basic의 경우).

다음 예제에서는 날짜 및 시간과 표준 시간대 정보가 모두 저장된 개체를 라운드트립하는 방법을 보여 줍니다.

Const fileName As String = ".\DateWithTz.dat"

Dim tempDate As Date = #9/3/2008 7:00:00 PM#
Dim tempTz As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
Dim dateWithTz As New DateInTimeZone(New DateTimeOffset(tempDate, _
                                         tempTz.GetUtcOffset(tempDate)), _
                                     tempTz)

' Store DateInTimeZone value to a file
Dim outFile As New FileStream(fileName, FileMode.Create)
Try
   Dim formatter As New BinaryFormatter()
   formatter.Serialize(outFile, dateWithTz)
   Console.WriteLine("Saving {0} {1} to {2}", dateWithTz.DateAndTime, _
           IIf(dateWithTz.TimeZone.IsDaylightSavingTime(dateWithTz.DateAndTime), _
               dateWithTz.TimeZone.DaylightName, dateWithTz.TimeZone.DaylightName), _
           fileName)
Catch e As SerializationException
   Console.WriteLine("Unable to serialize time data to {0}.", fileName)
Finally   
   outFile.Close()
End Try

' Retrieve DateInTimeZone value
If File.Exists(fileName) Then
   Dim inFile As New FileStream(fileName, FileMode.Open)
   Dim dateWithTz2 As New DateInTimeZone()
   Try
      Dim formatter As New BinaryFormatter()
      dateWithTz2 = DirectCast(formatter.Deserialize(inFile), DateInTimeZone)         
      Console.WriteLine("Restored {0} {1} from {2}", dateWithTz2.DateAndTime, _
                        IIf(dateWithTz2.TimeZone.IsDaylightSavingTime(dateWithTz2.DateAndTime), _
                        dateWithTz2.TimeZone.DaylightName, dateWithTz2.TimeZone.DaylightName), _
                        fileName)
   Catch e As SerializationException
      Console.WriteLine("Unable to retrieve date and time information from {0}", _
                        fileName)
   Finally            
      inFile.Close
   End Try
End If
' This example displays the following output to the console:
'    Saving 9/3/2008 7:00:00 PM -05:00 Central Daylight Time to .\DateWithTz.dat
'    Restored 9/3/2008 7:00:00 PM -05:00 Central Daylight Time from .\DateWithTz.dat      
const string fileName = @".\DateWithTz.dat";

DateTime tempDate = new DateTime(2008, 9, 3, 19, 0, 0);
TimeZoneInfo tempTz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateInTimeZone dateWithTz = new DateInTimeZone(new DateTimeOffset(tempDate, 
                                tempTz.GetUtcOffset(tempDate)), 
                                tempTz);

// Store DateInTimeZone value to a file
FileStream outFile = new FileStream(fileName, FileMode.Create);
try
{
   BinaryFormatter formatter = new BinaryFormatter();
   formatter.Serialize(outFile, dateWithTz);
   Console.WriteLine("Saving {0} {1} to {2}", dateWithTz.DateAndTime, 
                     dateWithTz.TimeZone.IsDaylightSavingTime(dateWithTz.DateAndTime) ? 
                     dateWithTz.TimeZone.DaylightName : dateWithTz.TimeZone.DaylightName, 
                     fileName);
}
catch (SerializationException)
{
   Console.WriteLine("Unable to serialize time data to {0}.", fileName);
}
finally
{         
   outFile.Close();
}

// Retrieve DateInTimeZone value
if (File.Exists(fileName))
{
   FileStream inFile = new FileStream(fileName, FileMode.Open);
   DateInTimeZone dateWithTz2 = new DateInTimeZone();
   try
   {
      BinaryFormatter formatter = new BinaryFormatter();
      dateWithTz2 = formatter.Deserialize(inFile) as DateInTimeZone;   
      Console.WriteLine("Restored {0} {1} from {2}", dateWithTz2.DateAndTime, 
                        dateWithTz2.TimeZone.IsDaylightSavingTime(dateWithTz2.DateAndTime) ? 
                        dateWithTz2.TimeZone.DaylightName : dateWithTz2.TimeZone.DaylightName, 
                        fileName);
   }
   catch (SerializationException)
   {
      Console.WriteLine("Unable to retrieve date and time information from {0}", 
                        fileName);
   }
   finally
   {
      inFile.Close();
   }
}
// This example displays the following output to the console:
//    Saving 9/3/2008 7:00:00 PM -05:00 Central Daylight Time to .\DateWithTz.dat
//    Restored 9/3/2008 7:00:00 PM -05:00 Central Daylight Time from .\DateWithTz.dat      

이 방법으로 라운드트립하면 저장 및 복원 전후의 정확한 시점이 항상 명확하게 반영됩니다. 단, 날짜 및 시간과 표준 시간대 개체를 조합했을 때 날짜 값이 표준 시간대 값과 항상 동기화되어야 합니다.

코드 컴파일

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

참고 항목

개념

형식 지정 방법 항목

DateTime, DateTimeOffset 및 TimeZoneInfo 중 선택

표준 날짜 및 시간 형식 문자열