Porady: obustronna konwersja wartości daty i godzinyHow to: Round-trip Date and Time Values

W wielu aplikacjach wartość daty i godziny ma na celu jednoznaczne zidentyfikowanie pojedynczego punktu w czasie.In many applications, a date and time value is intended to unambiguously identify a single point in time. W tym temacie pokazano, DateTime jak DateTimeOffset zapisać i przywrócić wartość, wartość i wartość daty i godziny z informacjami o strefie czasowej, dzięki czemu przywrócona wartość identyfikuje ten sam czas co zapisana wartość.This topic shows how to save and restore a DateTime value, a DateTimeOffset value, and a date and time value with time zone information so that the restored value identifies the same time as the saved value.

Aby obustronnie konwertować wartość daty/czasuTo round-trip a DateTime value

  1. Konwertuj wartość na DateTime DateTime.ToString(String) jego reprezentację ciągu, wywołując metodę z specyfikatorem formatu "o".Convert the DateTime value to its string representation by calling the DateTime.ToString(String) method with the "o" format specifier.

  2. Zapisz reprezentację ciągu DateTime wartości do pliku lub przekaż ją przez granicę procesu, domeny aplikacji lub komputera.Save the string representation of the DateTime value to a file, or pass it across a process, application domain, or machine boundary.

  3. Pobierz ciąg reprezentujący DateTime wartość.Retrieve the string that represents the DateTime value.

  4. Wywołać DateTime.Parse(String, IFormatProvider, DateTimeStyles) metodę i DateTimeStyles.RoundtripKind przekazać jako styles wartość parametru.Call the DateTime.Parse(String, IFormatProvider, DateTimeStyles) method, and pass DateTimeStyles.RoundtripKind as the value of the styles parameter.

W poniższym przykładzie przedstawiono sposób DateTime w obie strony wartości.The following example illustrates how to round-trip a DateTime value.

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.
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.

Podczas rundy potknięcia DateTime wartości, ta technika z powodzeniem zachowuje czas dla wszystkich lokalnych i uniwersalnych czasów.When round-tripping a DateTime value, this technique successfully preserves the time for all local and universal times. Jeśli na przykład DateTime wartość lokalna zostanie zapisana w systemie w standardowej strefie czasowej Stany Zjednoczonego Pacyfiku i zostanie przywrócona w systemie w strefie czasowej standardu centralnego usa, przywrócona data i godzina będą dwie godziny później spożące niż czas pierwotny, który odzwierciedla różnicę czasu między dwiema strefami czasowymi.For example, if a local DateTime value is saved on a system in the U.S. Pacific Standard Time zone and is restored on a system in the U.S. Central Standard Time zone, the restored date and time will be two hours later than the original time, which reflects the time difference between the two time zones. Jednak ta technika nie musi być dokładna dla nieokreślonych czasów.However, this technique is not necessarily accurate for unspecified times. Wszystkie DateTime wartości, Kind Unspecified których właściwość jest traktowana tak, jakby były czasami lokalnymi.All DateTime values whose Kind property is Unspecified are treated as if they are local times. Jeśli tak nie jest, DateTime nie zidentyfikuje pomyślnie prawidłowego punktu w czasie.If this is not the case, the DateTime will not successfully identify the correct point in time. Obejściem tego ograniczenia jest ścisłe sparowanie wartości daty i godziny ze strefą czasową dla operacji zapisywania i przywracania.The workaround for this limitation is to tightly couple a date and time value with its time zone for the save and restore operation.

Aby obustronnie konwertować wartość przesunięcia daty/czasuTo round-trip a DateTimeOffset value

  1. Konwertuj wartość na DateTimeOffset DateTimeOffset.ToString(String) jego reprezentację ciągu, wywołując metodę z specyfikatorem formatu "o".Convert the DateTimeOffset value to its string representation by calling the DateTimeOffset.ToString(String) method with the "o" format specifier.

  2. Zapisz reprezentację ciągu DateTimeOffset wartości do pliku lub przekaż ją przez granicę procesu, domeny aplikacji lub komputera.Save the string representation of the DateTimeOffset value to a file, or pass it across a process, application domain, or machine boundary.

  3. Pobierz ciąg reprezentujący DateTimeOffset wartość.Retrieve the string that represents the DateTimeOffset value.

  4. Wywołać DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) metodę i DateTimeStyles.RoundtripKind przekazać jako styles wartość parametru.Call the DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) method, and pass DateTimeStyles.RoundtripKind as the value of the styles parameter.

W poniższym przykładzie przedstawiono sposób DateTimeOffset w obie strony wartości.The following example illustrates how to round-trip a DateTimeOffset value.

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.
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.

Ta technika zawsze jednoznacznie DateTimeOffset identyfikuje wartość jako pojedynczy punkt w czasie.This technique always unambiguously identifies a DateTimeOffset value as a single point in time. Wartość można następnie przekonwertować na skoordynowany czas DateTimeOffset.ToUniversalTime uniwersalny (UTC) przez wywołanie metody lub można ją DateTimeOffset.ToOffset TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) przekonwertować na czas w określonej strefie czasowej, wywołując lub metody.The value can then be converted to Coordinated Universal Time (UTC) by calling the DateTimeOffset.ToUniversalTime method, or it can be converted to the time in a particular time zone by calling the DateTimeOffset.ToOffset or TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) method. Głównym ograniczeniem tej techniki jest to, że data i godzina arytmetyka, gdy wykonywane na DateTimeOffset wartość, która reprezentuje czas w określonej strefie czasowej, może nie dawać dokładne wyniki dla tej strefy czasowej.The major limitation of this technique is that date and time arithmetic, when performed on a DateTimeOffset value that represents the time in a particular time zone, may not produce accurate results for that time zone. Dzieje się tak, ponieważ gdy DateTimeOffset wartość jest tworzone, jest odłączony od jego strefy czasowej.This is because when a DateTimeOffset value is instantiated, it is disassociated from its time zone. W związku z tym reguły korekty tej strefy czasowej nie mogą być już stosowane podczas wykonywania obliczeń daty i godziny.Therefore, that time zone's adjustment rules can no longer be applied when you perform date and time calculations. Można obejść ten problem, definiując typ niestandardowy, który zawiera zarówno wartość daty i godziny, jak i towarzyszącą jej strefę czasową.You can work around this problem by defining a custom type that includes both a date and time value and its accompanying time zone.

Aby obustronnie konwertować wartość daty i czasu z ich strefą czasuTo round-trip a date and time value with its time zone

  1. Zdefiniuj klasę lub strukturę z dwoma polami.Define a class or a structure with two fields. Pierwsze pole to DateTime DateTimeOffset obiekt lub obiekt, a TimeZoneInfo drugie jest obiektem.The first field is either a DateTime or a DateTimeOffset object, and the second is a TimeZoneInfo object. Poniższy przykład jest prostą wersją takiego typu.The following example is a simple version of such a type.

    [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;
          }
       }
    }
    
    <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
    
  2. Oznacz klasę SerializableAttribute atrybutem.Mark the class with the SerializableAttribute attribute.

  3. Serializowania obiektu BinaryFormatter.Serialize przy użyciu metody.Serialize the object using the BinaryFormatter.Serialize method.

  4. Przywróć obiekt Deserialize za pomocą metody.Restore the object using the Deserialize method.

  5. Rzutować (w języku C#) lub konwertować (w języku Visual Basic) obiekt zdeserializowany do obiektu odpowiedniego typu.Cast (in C#) or convert (in Visual Basic) the deserialized object to an object of the appropriate type.

W poniższym przykładzie pokazano, jak w obie strony obiektu, który przechowuje zarówno daty i godziny i informacji o strefie czasowej.The following example illustrates how to round-trip an object that stores both date and time and time zone information.

   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      
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      

Technika ta powinna zawsze jednoznacznie odzwierciedlać prawidłowy punkt czasu zarówno przed, jak i po jego zapisaniu i przywróceniu, pod warunkiem, że implementacja połączonego obiektu daty i godziny oraz strefy czasowej nie pozwala, aby wartość daty nie była zsynchronizowana z obiektem wartości strefy czasowej.This technique should always unambiguously reflect the correct point of time both before and after it is saved and restored, provided that the implementation of the combined date and time and time zone object does not allow the date value to become out of sync with the time zone value.

Kompilowanie koduCompiling the Code

Poteki wymagają:These examples require:

Zobacz teżSee also