Vorgehensweise: Roundtrip-Datums- und -UhrzeitwerteHow to: Round-trip Date and Time Values

In vielen Anwendungen soll ein Datums- und Uhrzeitwert einen bestimmten Zeitpunkt eindeutig identifizieren.In many applications, a date and time value is intended to unambiguously identify a single point in time. In diesem Thema wird gezeigt, wie ein DateTime-Wert, ein DateTimeOffset-Wert sowie ein Datums- und Uhrzeitwert mit Zeitzoneninformationen so gespeichert und wiederhergestellt werden, dass der wiederhergestellte Wert denselben Zeitpunkt bezeichnet wie der gespeicherte Wert.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.

So führen Sie einen Roundtrip für einen DateTime-Wert durchTo round-trip a DateTime value

  1. Konvertieren Sie den DateTime-Wert in seine Zeichenfolgendarstellung, indem Sie die DateTime.ToString(String)-Methode mit dem Formatbezeichner „o“ aufrufen.Convert the DateTime value to its string representation by calling the DateTime.ToString(String) method with the "o" format specifier.

  2. Speichern Sie die Zeichenfolgendarstellung des DateTime-Werts in einer Datei, oder übergeben Sie sie über einen Prozess, eine Anwendungsdomäne oder eine Computergrenze.Save the string representation of the DateTime value to a file, or pass it across a process, application domain, or machine boundary.

  3. Rufen Sie die Zeichenfolge ab, die den DateTime-Wert darstellt.Retrieve the string that represents the DateTime value.

  4. Rufen Sie die DateTime.Parse(String, IFormatProvider, DateTimeStyles)-Methode auf, und übergeben Sie DateTimeStyles.RoundtripKind als Wert für den styles-Parameter.Call the DateTime.Parse(String, IFormatProvider, DateTimeStyles) method, and pass DateTimeStyles.RoundtripKind as the value of the styles parameter.

Das folgende Beispiel veranschaulicht, wie ein Roundtrip für einen DateTime-Wert ausgeführt wird.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.

Beim Ausführen von Roundtrips für einen DateTime-Wert wird durch diese Methode erfolgreich die Uhrzeit für alle Orts- und Weltzeiten beibehalten.When round-tripping a DateTime value, this technique successfully preserves the time for all local and universal times. Wenn beispielsweise ein lokaler DateTime-Wert auf einem System in der US-Zeitzone Pacific Standard Time gespeichert und auf einem System in der US-Zeitzone Central Standard Time wiederhergestellt wird, liegen das wiederhergestellte Datum und die Uhrzeit zwei Stunden hinter der ursprünglichen Zeit, was dem Zeitunterschied zwischen den beiden Zeitzonen entspricht.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. Dieses Verfahren ist für nicht spezifizierte Zeiten jedoch nicht notwendigerweise genau.However, this technique is not necessarily accurate for unspecified times. Alle DateTime-Werte, deren Kind-Eigenschaft auf Unspecified festgelegt ist, werden als Ortszeiten behandelt.All DateTime values whose Kind property is Unspecified are treated as if they are local times. Wenn dies nicht korrekt ist, kann der richtige Zeitpunkt durch DateTime nicht erfolgreich identifiziert werden.If this is not the case, the DateTime will not successfully identify the correct point in time. Die Umgehung für diese Einschränkung besteht darin, einen Datums- und Zeitwert für den Speicher- und Wiederherstellungsvorgang eng an die entsprechende Zeitzone zu koppeln.The workaround for this limitation is to tightly couple a date and time value with its time zone for the save and restore operation.

So führen Sie einen Roundtrip für einen DateTimeOffset-Wert durchTo round-trip a DateTimeOffset value

  1. Konvertieren Sie den DateTimeOffset-Wert in seine Zeichenfolgendarstellung, indem Sie die DateTimeOffset.ToString(String)-Methode mit dem Formatbezeichner „o“ aufrufen.Convert the DateTimeOffset value to its string representation by calling the DateTimeOffset.ToString(String) method with the "o" format specifier.

  2. Speichern Sie die Zeichenfolgendarstellung des DateTimeOffset-Werts in einer Datei, oder übergeben Sie sie über einen Prozess, eine Anwendungsdomäne oder eine Computergrenze.Save the string representation of the DateTimeOffset value to a file, or pass it across a process, application domain, or machine boundary.

  3. Rufen Sie die Zeichenfolge ab, die den DateTimeOffset-Wert darstellt.Retrieve the string that represents the DateTimeOffset value.

  4. Rufen Sie die DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles)-Methode auf, und übergeben Sie DateTimeStyles.RoundtripKind als Wert für den styles-Parameter.Call the DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) method, and pass DateTimeStyles.RoundtripKind as the value of the styles parameter.

Das folgende Beispiel veranschaulicht, wie ein Roundtrip für einen DateTimeOffset-Wert ausgeführt wird.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.

Durch diese Methode wird ein DateTimeOffset-Wert immer eindeutig als ein einziger Zeitpunkt identifiziert.This technique always unambiguously identifies a DateTimeOffset value as a single point in time. Der Wert kann dann durch Aufrufen der DateTimeOffset.ToUniversalTime-Methode in die koordinierte Weltzeit (UTC) oder durch Aufrufen der DateTimeOffset.ToOffset- oder TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo)-Methode in die Zeit einer bestimmten Zeitzone konvertiert werden.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. Die wesentliche Einschränkung dieser Methode liegt darin, dass die Datums- und Uhrzeitarithmetik möglicherweise keine genauen Ergebnisse für die jeweilige Zeitzone liefert, wenn sie bei einem DateTimeOffset-Wert durchgeführt wird, der die Zeit in einer bestimmten Zeitzone darstellt.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. Grund hierfür ist, dass die Zuordnung eines DateTimeOffset-Werts zu seiner Zeitzone bei seiner Instanziierung aufgehoben wird.This is because when a DateTimeOffset value is instantiated, it is disassociated from its time zone. Daher können die Anpassungsregeln für diese Zeitzone bei Datums- und Uhrzeitberechnungen nicht mehr angewendet werden.Therefore, that time zone's adjustment rules can no longer be applied when you perform date and time calculations. Sie können dieses Problem umgehen, indem Sie einen benutzerdefinierten Typ definieren, der sowohl einen Datums- und Uhrzeitwert als auch die dazugehörige Zeitzone enthält.You can work around this problem by defining a custom type that includes both a date and time value and its accompanying time zone.

So führen Sie einen Roundtrip für einen Datums- und Uhrzeitwert mit der jeweiligen Zeitzone durchTo round-trip a date and time value with its time zone

  1. Definieren Sie eine Klasse oder Struktur mit zwei Feldern.Define a class or a structure with two fields. Beim ersten Feld handelt es sich entweder um ein DateTime- oder ein DateTimeOffset-Objekt und beim zweiten um ein TimeZoneInfo-Objekt.The first field is either a DateTime or a DateTimeOffset object, and the second is a TimeZoneInfo object. Im folgenden Beispiel wird eine einfache Version eines solchen Typs gezeigt.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. Markieren Sie die Klasse mit dem Attribut SerializableAttribute.Mark the class with the SerializableAttribute attribute.

  3. Serialisieren Sie das Objekt mit der Methode BinaryFormatter.Serialize.Serialize the object using the BinaryFormatter.Serialize method.

  4. Stellen Sie das Objekt mit der Methode Deserialize wieder her.Restore the object using the Deserialize method.

  5. Wandeln Sie (in C#) das deserialisierte Objekt in ein Objekt des entsprechenden Typs um, oder konvertieren Sie es (in Visual Basic) in diesen Typ.Cast (in C#) or convert (in Visual Basic) the deserialized object to an object of the appropriate type.

Im folgenden Beispiel wird veranschaulicht, wie ein Roundtrip für ein Objekt durchgeführt wird, das sowohl Datum und Uhrzeit als auch Zeitzoneninformationen speichert.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      

Diese Methode sollte stets eindeutig den richtigen Zeitpunkt darstellen, bevor und nachdem dieser gespeichert und wiederhergestellt wurde, vorausgesetzt, dass die Implementierung des kombinierten Objekts aus Datum und Uhrzeit sowie Zeitzone sicherstellt, dass der Datumswert mit dem Zeitzonenwert synchron ist.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.

Kompilieren des CodesCompiling the Code

Diese Beispiele erfordern Folgendes:These examples require:

Siehe auchSee also