Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Obwohl sowohl die DateTime als auch die DateTimeOffset Strukturen Elemente bereitstellen, die arithmetische Operationen für ihre Werte ausführen, sind die Ergebnisse arithmetischer Vorgänge sehr unterschiedlich. Dieser Artikel untersucht diese Unterschiede, stellt sie in den Kontext verschiedener Grade des Zeitzonenbewusstseins in Datums- und Uhrzeitdaten und erörtert, wie man vollständig zeitzonenbewusste Vorgänge mit diesen Daten ausführt.
Vergleiche und arithmetische Vorgänge mit DateTime-Werten
Mit der DateTime.Kind-Eigenschaft kann ein DateTimeKind Wert dem Datum und der Uhrzeit zugewiesen werden, um anzugeben, ob es ortsgebundene Zeit, koordinierte Weltzeit (UTC) oder die Uhrzeit in einer nicht angegebenen Zeitzone darstellt. Diese begrenzten Zeitzoneninformationen werden jedoch ignoriert, wenn Datums- und Uhrzeitarithmetik für DateTimeKind Werte verglichen oder ausgeführt wird. Im folgenden Beispiel, das die aktuelle Ortszeit mit der aktuellen UTC-Zeit vergleicht, wird veranschaulicht, wie die Zeitzoneninformationen ignoriert werden.
using System;
public enum TimeComparison2
{
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,
utcTime.Kind,
(localTime - utcTime).Hours,
(localTime - utcTime).Minutes);
Console.WriteLine("The {0} time is {1} the {2} time.",
localTime.Kind,
Enum.GetName(typeof(TimeComparison2), localTime.CompareTo(utcTime)),
utcTime.Kind);
}
}
// 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.
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
Die CompareTo(DateTime)-Methode meldet, dass die Ortszeit früher als (oder kleiner als) die UTC-Zeit ist, und der Subtraktionsvorgang gibt an, dass der Unterschied zwischen UTC und der Ortszeit für ein System in der US-Pazifischen Standardzeitzone sieben Stunden beträgt. Da diese beiden Werte jedoch unterschiedliche Darstellungen eines einzelnen Zeitpunkts bereitstellen, ist in diesem Fall klar, dass das Zeitintervall vollständig auf den Offset der lokalen Zeitzone von UTC zurückzuführen ist.
Im Allgemeinen wirkt sich die DateTime.Kind-Eigenschaft nicht auf die Ergebnisse aus, die von Kind Vergleichs- und arithmetischen Methoden zurückgegeben werden (wie der Vergleich von zwei identischen Punkten in der Zeit zeigt), obwohl sie sich auf die Interpretation dieser Ergebnisse auswirken kann. Beispiel:
Das Ergebnis einer arithmetischen Operation, die auf zwei Datums- und Uhrzeitwerte angewandt wird, bei denen die DateTime.Kind-Eigenschaften beide DateTimeKind sind, spiegelt das tatsächliche Zeitintervall zwischen den beiden Werten wider. Ebenso spiegelt der Vergleich zweier solcher Datums- und Uhrzeitwerte genau die Beziehung zwischen Zeiten wider.
Das Ergebnis eines arithmetischen oder Vergleichsvorgangs, der auf zwei Datums- und Uhrzeitwerten ausgeführt wird, bei denen die DateTime.Kind-Eigenschaften beide gleich DateTimeKind sind, oder auf zwei Datums- und Uhrzeitwerten mit unterschiedlichen DateTime.Kind-Eigenschaftswerten, spiegelt den Unterschied in der Uhrzeit zwischen den beiden Werten wider.
Arithmetische oder Vergleichsvorgänge für lokale Datums- und Uhrzeitwerte berücksichtigen weder, ob ein bestimmter Wert mehrdeutig oder ungültig ist, noch berücksichtigen sie die Auswirkungen von Anpassungsregeln, die sich aus dem Übergang der lokalen Zeitzone zu oder von Sommerzeit ergeben.
Jeder Vorgang, der die Differenz zwischen UTC und einer lokalen Uhrzeit vergleicht oder berechnet, enthält ein Zeitintervall, das dem Offset der lokalen Zeitzone von UTC im Ergebnis entspricht.
Jeder Vorgang, der die Differenz zwischen einer nicht angegebenen Zeit und entweder UTC oder der ortsspezifischen Uhrzeit vergleicht oder berechnet, spiegelt die einfache Uhrzeit wider. Zeitzonenunterschiede werden nicht berücksichtigt, und das Ergebnis spiegelt nicht die Anwendung von Anpassungsregeln für Zeitzonen wider.
Jeder Vorgang, der die Differenz zwischen zwei nicht angegebenen Zeiten vergleicht oder berechnet, kann ein unbekanntes Intervall enthalten, das den Unterschied zwischen der Zeit in zwei verschiedenen Zeitzonen widerspiegelt.
Es gibt viele Szenarien, in denen sich Unterschiede zwischen Zeitzonen und Datums- und Uhrzeitberechnungen nicht auswirken (eine Erläuterung einiger dieser Szenarien finden Sie unter Auswählen zwischen DateTime, DateTimeOffset, TimeSpan und TimeZoneInfo) oder in denen der Kontext der Datums- und Uhrzeitdaten die Bedeutung von Vergleichs- oder arithmetischen Vorgängen definiert.
Vergleiche und arithmetische Vorgänge mit DateTimeOffset-Werten
Ein DateTimeOffset Wert enthält nicht nur ein Datum und eine Uhrzeit, sondern auch einen Offset, der dieses Datum und diese Uhrzeit eindeutig im Verhältnis zu UTC definiert. Dieser Offset ermöglicht es, die Gleichheit anders zu definieren als für DateTime Werte. Während DateTime Werte gleich sind, wenn sie denselben Datums- und Uhrzeitwert aufweisen, sind DateTimeOffset Werte gleich, wenn beide auf denselben Zeitpunkt verweisen. Bei Vergleichen und den meisten arithmetischen Operationen, die das Intervall zwischen zwei Datums- und Uhrzeitangaben bestimmen, ist ein DateTimeOffset-Wert genauer und erfordert weniger Interpretation. Das folgende Beispiel, das für DateTimeOffset dem vorherigen Beispiel entspricht, welches lokale und UTC-DateTimeOffset Werte verglichen hat, veranschaulicht diesen Unterschied im Verhalten.
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: {(localTime - utcTime).Hours}:{(localTime - utcTime).Minutes:D2} hours");
Console.WriteLine($"The local time is {Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime))} UTC.");
}
}
// 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.
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}:{1: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)
In diesem Beispiel gibt die CompareTo-Methode an, dass die aktuelle Ortszeit und die aktuelle UTC-Zeit gleich sind, und subtraktion von CompareTo(DateTimeOffset) Werten gibt an, dass der Unterschied zwischen den beiden Zeiten TimeSpan.Zeroist.
Die haupteinschränkung der Verwendung von DateTimeOffset Werten in Datums- und Uhrzeitarithmetik besteht darin, dass DateTimeOffset Werte zwar ein gewisses Zeitzonenbewusstsein aufweisen, aber sie sind nicht vollständig zeitzonenfähig. Obwohl der Offset des DateTimeOffset-Werts den Offset einer Zeitzone von UTC widerspiegelt, wenn einer DateTimeOffset-Variablen zuerst ein Wert zugewiesen wird, wird er danach von der Zeitzone getrennt. Da sie nicht mehr direkt mit einer identifizierbaren Uhrzeit verknüpft ist, berücksichtigt das Hinzufügen und Subtraktion von Datums- und Zeitintervallen nicht die Anpassungsregeln einer Zeitzone.
Zur Veranschaulichung erfolgt der Übergang zur Sommerzeit in der Zeitzone "Central Standard" der USA um 2:00 Uhr am 9. März 2008. Damit sollte das Hinzufügen eines Intervalls von zweieinhalb Stunden zu einer Zentralen Standardzeit von 1:30 Uhr am 9. März 2008 ein Datum und eine Uhrzeit von 5:00 Uhr am 9. März 2008 erzeugen. Wie im folgenden Beispiel gezeigt wird, lautet das Ergebnis der Addition jedoch 4:00 Uhr vormittags am 9. März 2008. Das Ergebnis dieses Vorgangs stellt den richtigen Zeitpunkt dar, obwohl es sich nicht um die Uhrzeit in der Zeitzone handelt, in der wir interessiert sind (d. a. es hat nicht den erwarteten Zeitzonenversatz).
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($"{centralTime1} + {twoAndAHalfHours.ToString()} hours = {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
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
Arithmetische Vorgänge mit Zeiten in Zeitzonen
Die TimeZoneInfo Klasse enthält Konvertierungsmethoden, die automatisch Anpassungen anwenden, wenn sie Zeiten von einer Zeitzone in eine andere konvertieren. Zu diesen Konvertierungsmethoden gehören:
Die Methoden ConvertTime und ConvertTimeBySystemTimeZoneId, die Zeiten zwischen zwei Zeitzonen konvertieren.
Die methoden ConvertTimeFromUtc und ConvertTimeToUtc, die die Uhrzeit in einer bestimmten Zeitzone in UTC konvertieren oder UTC in die Uhrzeit in einer bestimmten Zeitzone konvertieren.
Ausführliche Informationen finden Sie unter Konvertieren von Zeiten zwischen Zeitzonen.
Die klasse TimeZoneInfo stellt keine Methoden bereit, die beim Ausführen von Datums- und Uhrzeitarithmetik automatisch Anpassungsregeln anwenden. Sie können jedoch Anpassungsregeln anwenden, indem Sie die Zeit in einer Zeitzone in UTC konvertieren, den arithmetischen Vorgang ausführen und dann von UTC zurück in die Zeit in der Zeitzone konvertieren. Ausführliche Informationen finden Sie unter wie man Zeitzonen in der Datums- und Uhrzeitarithmetik verwendet.
Der folgende Code ähnelt beispielsweise dem vorherigen Code, durch den am 9. März 2008 um 2:00 Uhr zweieinhalb Stunden hinzugefügt wurden. Da sie jedoch vor der Ausführung von Datums- und Uhrzeitarithmetik eine Zentrale Standardzeit in UTC konvertiert und dann das Ergebnis von UTC zurück in die Zentralstandardzeit konvertiert, spiegelt die resultierende Zeit den Übergang der Zentralen Standardzeitzone zu Sommerzeit wider.
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($"{centralTime1} + {twoAndAHalfHours.ToString()} hours = {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
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