Durchführen arithmetischer Datums- und Uhrzeitoperationen
Aktualisiert: November 2007
Die DateTime-Struktur und die DateTimeOffset-Struktur stellen zwar beide Member bereit, die arithmetische Operationen für ihre Werte durchführen, die Ergebnisse dieser arithmetischen Operationen fallen jedoch sehr unterschiedlich aus. In diesem Thema werden diese Unterschiede untersucht, mit der jeweiligen Zeitzonenunterstützung für Datums- und Uhrzeitdaten in Beziehung gesetzt und Informationen zur Durchführung von Operationen mit vollständiger Zeitzonenunterstützung für Datums- und Uhrzeitdaten bereitgestellt.
Vergleiche und arithmetische Operationen mit "DateTime"-Werten
Ab .NET Framework, Version 2.0, bieten DateTime-Werte eine eingeschränkte Unterstützung von Zeitzonen. Mit der DateTime.Kind-Eigenschaft kann ein DateTimeKind-Wert einem Datum und einer Uhrzeit zugewiesen werden, um anzugeben, ob es sich um die lokale Zeit, die koordinierte Weltzeit (UTC) oder die Zeit in einer nicht angegebenen Zeitzone handelt. Diese eingeschränkten Zeitzoneninformationen werden jedoch ignoriert, wenn DateTime-Werte verglichen oder arithmetische Datums- und Uhrzeitoperationen für sie durchgeführt werden. Im folgenden Beispiel, in dem die aktuelle lokale Zeit mit der aktuellen UTC-Zeit verglichen wird, wird dies veranschaulicht.
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
using System;
public enum TimeComparison
{
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.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(typeof(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.
Die CompareTo(DateTime)-Methode gibt an, dass die lokale Zeit früher als die UTC-Zeit ist, und die Subtraktionsoperation ergibt, dass der Unterschied zwischen der UTC-Zeit und der lokalen Zeit für ein System in der Zeitzone Pacific Normalzeit sieben Stunden beträgt. Da diese beiden Werte jedoch unterschiedliche Darstellungen eines bestimmten Zeitpunkts liefern, ist in diesem Fall klar, dass das Zeitintervall vollständig dem Offset der lokalen Zeitzone von der UTC-Zeit zuzuordnen ist.
Verallgemeinert bedeutet dies, dass sich die DateTime.Kind-Eigenschaft nicht auf die von DateTime-Methoden für Vergleiche und arithmetische Operationen zurückgegebenen Ergebnisse auswirkt (wie der Vergleich zweier identischer Zeitpunkte zeigt), aber die Interpretation dieser Ergebnisse beeinflussen kann. Hierzu ein Beispiel:
Das Ergebnis einer beliebigen arithmetischen Operation für zwei Datums- und Uhrzeitwerte, deren DateTime.Kind-Eigenschaft jeweils Utc entspricht, gibt das tatsächliche Zeitintervall zwischen den beiden Werten wieder. Der Vergleich zweier solcher Datums- und Uhrzeitwerte gibt entsprechend die Beziehung zwischen den Zeiten genau wieder.
Das Ergebnis einer arithmetischen oder Vergleichsoperation für zwei Datums- und Uhrzeitwerte, deren DateTime.Kind-Eigenschaft jeweils Local entspricht, oder für zwei Datums- und Uhrzeitwerte mit verschiedenen DateTime.Kind-Eigenschaftswerten gibt den Zeitunterschied zwischen den beiden Werten wieder.
Bei arithmetischen oder Vergleichsoperationen für lokale Datums- und Uhrzeitwerte wird nicht berücksichtigt, ob ein bestimmter Wert mehrdeutig oder ungültig ist. Zudem werden die Auswirkungen von Anpassungsregeln ignoriert, die aus dem Übergang der lokalen Zeitzone von oder zur Sommerzeit resultieren.
Das Ergebnis einer Operation, mit der der Unterschied zwischen der UTC-Zeit und der lokalen Zeit verglichen oder berechnet wird, beinhaltet ein Zeitintervall, das dem Offset der lokalen Zeitzone von der koordinierten Weltzeit entspricht.
Jede Operation, mit der der Unterschied zwischen einer nicht spezifizierten Zeit und der UTC-Zeit oder der lokalen Zeit verglichen oder berechnet wird, gibt die einfache Uhrzeit wieder. Zeitzonenunterschiede und entsprechende Anpassungsregeln werden ignoriert und im Ergebnis nicht wiedergegeben.
Jede Operation, mit der der Unterschied zwischen zwei nicht spezifizierten Zeiten verglichen oder berechnet wird, kann ein unbekanntes Intervall beinhalten, das den Unterschied zwischen der Zeit in zwei verschiedenen Zeitzonen wiedergibt.
Es gibt viele Szenarios, in denen sich Zeitzonenunterschiede nicht auf Datums- und Uhrzeitberechnungen auswirken (einige Beispiele finden Sie unter Auswählen zwischen "DateTime", "DateTimeOffset" und "TimeZoneInfo") oder in denen der Kontext von Datums- und Uhrzeitdaten die Bedeutung von Vergleichen oder arithmetischen Operationen definiert.
Vergleiche und arithmetische Operationen mit "DateTimeOffset"-Werten
Ein DateTimeOffset-Wert enthält nicht nur ein Datum und eine Uhrzeit, sondern auch einen Offset, der das Datum und die Uhrzeit bezogen auf die koordinierte Weltzeit eindeutig definiert. Dadurch ist es möglich, eine etwas andere Definition von Gleichheit als für DateTime-Werte zu verwenden. Während DateTime-Werte gleich sind, wenn sie den gleichen Datums- und Uhrzeitwert aufweisen, sind DateTimeOffset-Werte gleich, wenn sie sich beide auf den gleichen Zeitpunkt beziehen. Ein DateTimeOffset-Wert ist somit genauer und erfordert in Vergleichen und den meisten arithmetischen Operationen, mit denen das Intervall zwischen Datums- und Uhrzeitwerten bestimmt wird, einen geringeren Interpretationsaufwand. Dieser Verhaltensunterschied wird im folgenden Beispiel veranschaulicht, das dem DateTimeOffset-Äquivalent zum vorherigen Beispiel entspricht, in dem DateTime-Werte für die lokale Zeit und die UTC-Zeit verglichen wurden.
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}:{0: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)
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.
In diesem Beispiel gibt die CompareTo-Methode an, dass die aktuelle lokale Zeit und die aktuelle UTC-Zeit identisch sind, und die Subtraktion von DateTimeOffset-Werten ergibt, dass der Unterschied zwischen den beiden Zeiten TimeSpan.Zero ist.
Die größte Einschränkung bei der Verwendung von DateTimeOffset-Werten in arithmetischen Datums- und Uhrzeitoperationen besteht darin, dass DateTimeOffset-Werte keine vollständige Zeitzonenunterstützung bieten. Wenn einer DateTimeOffset-Variablen ein Wert zugeordnet wird, gibt dieser DateTimeOffset-Wert zunächst zwar den Offset einer Zeitzone von der koordinierten Weltzeit wieder, seine Zuordnung zur Zeitzone wird anschließend jedoch aufgehoben. Da er keiner identifizierbaren Zeit mehr direkt zugeordnet ist, werden bei der Addition und Subtraktion von Datums- und Uhrzeitintervallen die Anpassungsregeln einer Zeitzone nicht berücksichtigt.
Hier ein Beispiel zur Veranschaulichung: Der Übergang zur Sommerzeit erfolgt in der Zeitzone Central Normalzeit am 9. März 2008 um 2:00 Uhr. Das bedeutet, dass sich durch Hinzufügen eines 2 1/2-Stunden-Intervalls zum Datums- und Uhrzeitwert 9. März 2008, 1:30 Uhr der Datums- und Uhrzeitwert 9. März 2008, 5:00 Uhr ergeben müsste. Wie das folgende Beispiel zeigt, ist das Ergebnis der Addition jedoch der 9. März 2008, 4:00 Uhr. Beachten Sie, dass das Ergebnis dieser Operation den richtigen Zeitpunkt wiedergibt, auch wenn es nicht die Zeit in der Zeitzone ist, die uns interessiert (d. h. es entspricht nicht dem erwarteten Zeitzonenoffset).
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
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
Arithmetische Operationen mit Zeiten in Zeitzonen
Die TimeZoneInfo-Klasse beinhaltet eine Reihe von Konvertierungsmethoden, die automatisch Anpassungen anwenden, wenn sie die Zeiten einer Zeitzone in die einer anderen konvertieren. Hierzu gehört Folgendes:
Die ConvertTime-Methode und die ConvertTimeBySystemTimeZoneId-Methode, die Zeiten zwischen zwei beliebigen Zeitzonen konvertieren.
Die ConvertTimeFromUtc-Methode und die ConvertTimeToUtc-Methode, die die Zeit in einer bestimmten Zeitzone in die koordinierte Weltzeit konvertieren oder umgekehrt.
Ausführliche Informationen finden Sie unter Konvertieren von Uhrzeiten zwischen Zeitzonen.
Die TimeZoneInfo-Klasse stellt keine Methoden bereit, die beim Durchführen von arithmetischen Datums- und Uhrzeitoperationen automatisch Anpassungsregeln anwenden. Dies ist jedoch möglich, indem Sie die Zeit in einer Zeitzone in die koordinierte Weltzeit konvertieren, die arithmetische Operation durchführen und anschließend die koordinierte Weltzeit wieder in die Zeit in der Zeitzone konvertieren. Ausführliche Informationen finden Sie unter Gewusst wie: Verwenden von Zeitzonen in arithmetischen Datums- und Uhrzeitoperationen.
Der folgende Code ist z. B. ähnlich wie der vorherige Code, durch den zweieinhalb Stunden zum Datums- und Uhrzeitwert 9. März 2008, 2:00 Uhr hinzugefügt wurden. Da er jedoch eine Zeit in der Zeitzone Central Normalzeit in die koordinierte Weltzeit konvertiert, bevor er arithmetische Datums- und Uhrzeitoperationen durchführt, und danach das Ergebnis von der koordinierten Weltzeit wieder in die Central Normalzeit konvertiert, gibt die Zeit den Übergang der Zeitzone Central Normalzeit zur Sommerzeit wieder.
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
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
Siehe auch
Aufgaben
Gewusst wie: Verwenden von Zeitzonen in arithmetischen Datums- und Uhrzeitoperationen