Exécution d'opérations arithmétiques avec des dates et heures
Mise à jour : novembre 2007
Même si les structures DateTime et DateTimeOffset fournissent des membres qui exécutent des opérations arithmétiques sur leurs valeurs, les résultats des opérations arithmétiques sont très différents. Cette rubrique examine ces différences, les met en rapport avec les degrés de prise en charge des fuseaux horaires dans les données de date et d'heure et explique comment exécuter des opérations prenant pleinement en charge les fuseaux horaires à l'aide de données de date et d'heure.
Comparaisons et opérations arithmétiques avec des valeurs DateTime
À partir de .NET Framework version 2.0, les valeurs DateTime possèdent un degré limité de prise en charge des fuseaux horaires. La propriété DateTime.Kind permet d'assigner une valeur DateTimeKind à la date et à l'heure pour indiquer si elle représente l'heure locale, le temps universel coordonné (UTC, Coordinated Universal Time) ou l'heure dans un fuseau horaire non spécifié. Ces informations limitées sur les fuseaux horaires sont toutefois ignorées lors de la comparaison ou de l'exécution d'opérations arithmétiques avec des dates et des heures sur les valeurs DateTime. Ceci est illustré dans l'exemple suivant qui compare l'heure locale actuelle à l'heure UTC actuelle.
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.
La méthode CompareTo(DateTime) indique que l'heure locale est antérieure (ou inférieure) à l'heure UTC et l'opération de soustraction indique que la différence entre l'heure UTC et l'heure locale pour un système se trouvant dans le fuseau horaire de l'heure normale du Pacifique (États-Unis) s'élève à sept heures. Mais comme ces deux valeurs donnent des représentations différentes d'un même point dans le temps, il apparaît clairement dans ce cas que cet intervalle de temps est totalement attribuable au décalage du fuseau horaire local par rapport à l'heure UTC.
De manière générale, la propriété DateTime.Kind n'influe pas sur les résultats retournés par des méthodes de comparaison et d'arithmétique DateTime (comme la comparaison de deux points identiques dans le temps l'indique), mais elle peut influer sur l'interprétation de ces résultats. Par exemple :
Le résultat de toute opération arithmétique exécutée sur deux valeurs de date et d'heure dont les propriétés DateTime.Kind sont égales à Utc indique l'intervalle de temps effectif entre ces deux valeurs. De même, la comparaison de deux valeurs de date et d'heure de ce type indique précisément la relation entre les heures.
Le résultat de toute opération arithmétique ou opération de comparaison exécutée sur deux valeurs de date et d'heure dont les propriétés DateTime.Kind sont égales à Local ou sur deux valeurs de date et d'heure dont les propriétés DateTime.Kind ont des valeurs différentes indique la différence en temps horloge entre ces deux valeurs.
Les opérations arithmétiques ou les opérations de comparaison sur des valeurs de date et d'heure locales ne se soucient pas de savoir si une valeur particulière est ambiguë ou non valide et ne tiennent pas non plus compte de l'incidence de règles d'ajustement qui résultent du passage du fuseau horaire local à l'heure d'été ou à l'heure d'hiver.
Toute opération qui compare ou calcule la différence entre l'heure UTC et une heure locale inclut un intervalle de temps égal au décalage du fuseau horaire local par rapport à l'heure UTC dans le résultat.
Toute opération qui compare ou calcule la différence entre une heure non spécifiée et l'heure UTC ou l'heure locale indique le temps horloge simple. Les décalages entre les fuseaux horaires ne sont pas pris en compte et le résultat ne tient pas compte de l'application de règles d'ajustement des fuseaux horaires.
Toute opération qui compare ou calcule la différence entre deux heures non spécifiées peut inclure un intervalle inconnu qui indique la différence horaire dans deux fuseaux horaires différents.
Nombreux sont les scénarios dans lesquels les décalages entre les fuseaux horaires n'influent pas sur les calculs des dates et des heures (pour plus d'informations sur certains d'entre eux, consultez Choix entre DateTime, DateTimeOffset et TimeZoneInfo) ou dans lesquels le contexte des données de date et d'heure définit la signification des opérations de comparaison ou des opérations arithmétiques.
Comparaisons et opérations arithmétiques avec des valeurs DateTimeOffset
Une valeur DateTimeOffset inclut non seulement une date et une heure, mais également un décalage qui définit clairement cette date et cette heure par rapport à l'heure UTC. Il est ainsi possible de définir une égalité d'une manière quelque peu différente de celle des valeurs DateTime. Les valeurs DateTime sont égales lorsqu'elles possèdent la même valeur de date et d'heure, alors que les valeurs DateTimeOffset sont égales lorsqu'elles font toutes les deux référence au même point dans le temps. Une valeur DateTimeOffset est de ce fait plus précise et nécessite moins d'interprétation lorsqu'elle est utilisée dans des comparaisons et dans la plupart des opérations arithmétiques qui déterminent l'intervalle entre deux dates et heures. Cette différence de comportement est illustrée dans l'exemple suivant, qui est l'équivalent DateTimeOffset de l'exemple précédent dans lequel les valeurs DateTime de l'heure locale et de l'heure UTC étaient comparées.
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.
Dans cet exemple, la méthode CompareTo indique que l'heure locale actuelle et l'heure UTC actuelle sont égales et la soustraction des valeurs DateTimeOffset indique que la différence entre les deux heures est TimeSpan.Zero.
L'utilisation de valeurs DateTimeOffset dans des opérations arithmétiques de date et d'heure présente une sérieuse limitation : même si les valeurs DateTimeOffset prennent en charge certains fuseaux horaires, elles ne prennent pas en charge tous les fuseaux horaires. Même si le décalage de la valeur DateTimeOffset indique le décalage d'un fuseau horaire par rapport à l'heure UTC lorsqu'une première valeur est assignée à une variable DateTimeOffset, il se dissocie par la suite du fuseau horaire. Comme il n'est plus directement associé à une heure identifiable, les règles d'ajustement d'un fuseau horaire ne sont pas prises en compte lors de l'addition et de la soustraction d'intervalles de dates et d'heures.
Par exemple, le passage à l'heure d'été dans le fuseau horaire de l'heure du Centre (des États-Unis) se produit à 2 h le 9 mars 2008. En d'autres termes, l'addition d'un intervalle de deux heures et demie à une heure du Centre de 1 h 30 le 9 mars 2008 doit générer une heure et une date de 5 h le 9 mars 2008. Comme le montre l'exemple suivant, le résultat de l'addition est toutefois 4 h le 9 mars 2008. Notez que le résultat de cette opération représente le point correct dans le temps, même s'il ne correspond pas à l'heure dans le fuseau horaire concerné (autrement dit, il ne correspond pas au décalage attendu dans le fuseau horaire).
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
Opérations arithmétiques avec des heures et des fuseaux horaires
La classe TimeZoneInfo inclut plusieurs méthodes de conversion qui appliquent automatiquement des ajustements lorsqu'elles convertissent des heures d'un fuseau horaire à un autre. Parmi celles-ci figurent :
Les méthodes ConvertTime et ConvertTimeBySystemTimeZoneId, qui convertissent des heures d'un fuseau horaire à un autre.
Les méthodes ConvertTimeFromUtc et ConvertTimeToUtc, qui convertissent l'heure d'un fuseau horaire particulier en heure UTC ou qui convertissent l'heure UTC dans l'heure d'un fuseau horaire particulier.
Pour plus d'informations, consultez Conversion d'heures entre fuseaux horaires.
La classe TimeZoneInfo ne fournit pas de méthodes qui appliquent automatiquement des règles d'ajustement lorsque vous exécutez des opérations arithmétiques de date et d'heure. Vous pouvez toutefois procéder en convertissant l'heure d'un fuseau horaire en heure UTC, en exécutant l'opération arithmétique, puis en reconvertissant l'heure UTC dans l'heure du fuseau horaire. Pour plus d'informations, consultez Comment : utiliser des fuseaux horaires en arithmétique de date et heure.
Par exemple, le code suivant est semblable au code précédent qui a additionné deux heures et demie à 2 h le 9 mars 2008. Toutefois, comme il convertit une heure du Centre (des États-Unis) en heure UTC avant d'exécuter une opération arithmétique de date et d'heure et reconvertit ensuite le résultat de l'heure UTC en heure du Centre, l'heure résultante reflète le passage à l'heure d'été de l'heure du Centre.
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
Voir aussi
Tâches
Comment : utiliser des fuseaux horaires en arithmétique de date et heure