Conversion des heures entre les fuseaux horaires

Il devient de plus en plus important pour toute application qui fonctionne avec des dates et des heures pour gérer les différences entre les fuseaux horaires. Une application ne peut plus supposer que toutes les heures peuvent être exprimées dans l’heure locale, c’est-à-dire l’heure disponible à partir de la DateTime structure. Par exemple, une page web qui affiche l’heure actuelle dans la partie est des États-Unis manquera de crédibilité à un client de l’est de l’Asie. Cet article explique comment convertir des heures d’un fuseau horaire à un autre et convertir des DateTimeOffset valeurs qui ont une sensibilité limitée au fuseau horaire.

Conversion en temps universel coordonné

Le temps universel coordonné (UTC) est un standard de temps atomique de haute précision. Les fuseaux horaires du monde sont exprimés sous forme de décalages positifs ou négatifs par rapport à l’heure UTC. Par conséquent, UTC fournit un fuseau horaire libre ou un fuseau horaire neutre. L’utilisation d’UTC est recommandée lorsqu’une portabilité de date et d’heure sur les ordinateurs est importante. Pour plus d’informations et d’autres bonnes pratiques à l’aide de dates et d’heures, consultez les meilleures pratiques de codage à l’aide de DateTime dans le .NET Framework. La conversion de fuseaux horaires individuels en fuseau horaire UTC facilite les comparaisons de temps.

Note

Vous pouvez également sérialiser une DateTimeOffset structure pour représenter un point unique dans le temps sans ambiguïté. Étant donné que les objets stockent une valeur de date et d’heure ainsi que DateTimeOffset son décalage par rapport à UTC, ils représentent toujours un point particulier dans l’heure par rapport à UTC.

Le moyen le plus simple de convertir une heure au format UTC consiste à appeler la static méthode (Shareden Visual Basic). TimeZoneInfo.ConvertTimeToUtc(DateTime) La conversion exacte effectuée par la méthode dépend de la valeur de la dateTime propriété du Kind paramètre, comme le montre le tableau suivant :

DateTime.Kind Conversion
DateTimeKind.Local Convertit l’heure locale en heure UTC.
DateTimeKind.Unspecified Suppose que le dateTime paramètre est l’heure locale et convertit l’heure locale en heure UTC.
DateTimeKind.Utc Retourne le dateTime paramètre inchangé.

Le code suivant convertit l’heure locale actuelle en heure UTC et affiche le résultat dans la console :

DateTime dateNow = DateTime.Now;
Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(dateNow)} UTC.");
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
                  TimeZoneInfo.ConvertTimeToUtc(dateNow))

Si la valeur de date et d’heure ne représente pas l’heure locale ou UTC, la ToUniversalTime méthode retourne probablement un résultat erroné. Toutefois, vous pouvez utiliser la TimeZoneInfo.ConvertTimeToUtc méthode pour convertir la date et l’heure à partir d’un fuseau horaire spécifié. Pour plus d’informations sur la récupération d’un TimeZoneInfo objet qui représente le fuseau horaire de destination, consultez Recherche des fuseaux horaires définis sur un système local. Le code suivant utilise la méthode pour convertir l’heure standard de l’Est TimeZoneInfo.ConvertTimeToUtc en heure UTC :

DateTime easternTime = new DateTime(2007, 01, 02, 12, 16, 00);
string easternZoneId = "Eastern Standard Time";
try
{
    TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
    Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)} UTC.");
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine($"Unable to find the {easternZoneId} zone in the registry.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine($"Registry data on the {easternZoneId} zone has been corrupted.");
}
Dim easternTime As New Date(2007, 01, 02, 12, 16, 00)
Dim easternZoneId As String = "Eastern Standard Time"
Try
    Dim easternZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId)
    Console.WriteLine("The date and time are {0} UTC.", _
                      TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("Unable to find the {0} zone in the registry.", _
                      easternZoneId)
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the {0} zone has been corrupted.", _
                      easternZoneId)
End Try

La méthode TimeZoneInfo.ConvertTimeToUtc lève une ArgumentException si la propriété Kind de l’objet DateTime et le fuseau horaire ne correspondent pas. Une incompatibilité se produit si la propriété Kind est DateTimeKind.Local mais que l’objet TimeZoneInfo ne représente pas le fuseau horaire local, ou si la propriété Kind est DateTimeKind.Utc mais que l’objet TimeZoneInfo n’est pas égal à TimeZoneInfo.Utc.

Toutes ces méthodes prennent DateTime des valeurs comme paramètres et retournent une DateTime valeur. Pour DateTimeOffset les valeurs, la DateTimeOffset structure a une méthode d’instance ToUniversalTime qui convertit la date et l’heure de l’instance actuelle en UTC. L’exemple suivant appelle la ToUniversalTime méthode pour convertir une heure locale et plusieurs autres fois en UTC :

DateTimeOffset localTime, otherTime, universalTime;

// Define local time in local time zone
localTime = new DateTimeOffset(new DateTime(2007, 6, 15, 12, 0, 0));
Console.WriteLine($"Local time: {localTime}");
Console.WriteLine();

// Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero);
Console.WriteLine($"Other time: {otherTime}");
Console.WriteLine($"{localTime} = {otherTime}: {localTime.Equals(otherTime)}");
Console.WriteLine($"{localTime} exactly equals {otherTime}: {localTime.EqualsExact(otherTime)}");
Console.WriteLine();

// Convert other time to UTC
universalTime = localTime.ToUniversalTime();
Console.WriteLine($"Universal time: {universalTime}");
Console.WriteLine($"{otherTime} = {universalTime}: {universalTime.Equals(otherTime)}");
Console.WriteLine($"{otherTime} exactly equals {universalTime}: {universalTime.EqualsExact(otherTime)}");
Console.WriteLine();

// The example produces the following output to the console:
//    Local time: 6/15/2007 12:00:00 PM -07:00
//
//    Other time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
//
//    Universal time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True
Dim localTime, otherTime, universalTime As DateTimeOffset

' Define local time in local time zone
localTime = New DateTimeOffset(#6/15/2007 12:00:00PM#)
Console.WriteLine("Local time: {0}", localTime)
Console.WriteLine()

' Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero)
Console.WriteLine("Other time: {0}", otherTime)
Console.WriteLine("{0} = {1}: {2}", _
                  localTime, otherTime, _
                  localTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  localTime, otherTime, _
                  localTime.EqualsExact(otherTime))
Console.WriteLine()

' Convert other time to UTC
universalTime = localTime.ToUniversalTime()
Console.WriteLine("Universal time: {0}", universalTime)
Console.WriteLine("{0} = {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.EqualsExact(otherTime))
Console.WriteLine()
' The example produces the following output to the console:
'    Local time: 6/15/2007 12:00:00 PM -07:00
'    
'    Other time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
'    
'    Universal time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True   

Conversion UTC vers un fuseau horaire désigné

Pour convertir l’heure UTC en heure locale, consultez la section Conversion UTC en heure locale qui suit. Pour convertir UTC en heure dans n’importe quel fuseau horaire que vous désignez, appelez la ConvertTimeFromUtc méthode. La méthode accepte deux paramètres :

  • UTC à convertir. Il doit s’agir d’une DateTime valeur dont la propriété Kind est définie sur Unspecified ou Utc.

  • Fuseau horaire dans lequel convertir l'heure UTC.

Le code suivant convertit UTC en heure standard centrale :

DateTime timeUtc = DateTime.UtcNow;
try
{
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    Console.WriteLine("The date and time are {0} {1}.",
                      cstTime,
                      cstZone.IsDaylightSavingTime(cstTime) ?
                              cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Central Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.");
}
Dim timeUtc As Date = Date.UtcNow
Try
    Dim cstZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
    Dim cstTime As Date = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone)
    Console.WriteLine("The date and time are {0} {1}.", _
                      cstTime, _
                      IIf(cstZone.IsDaylightSavingTime(cstTime), _
                          cstZone.DaylightName, cstZone.StandardName))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Central Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.")
End Try

Conversion de l’heure UTC en heure locale

Pour convertir l’heure UTC en heure locale, appelez la ToLocalTime méthode de l’objet DateTime dont vous souhaitez convertir l’heure. Le comportement exact de la méthode dépend de la valeur de la propriété de Kind l’objet, comme le montre le tableau suivant :

DateTime.Kind Conversion
DateTimeKind.Local Retourne la DateTime valeur inchangée.
DateTimeKind.Unspecified Suppose que la DateTime valeur est UTC et convertit l’heure UTC en heure locale.
DateTimeKind.Utc Convertit la DateTime valeur en heure locale.

Note

La TimeZone.ToLocalTime méthode se comporte de façon identique à la DateTime.ToLocalTime méthode. Il prend un paramètre unique, qui est la valeur de date et d'heure à convertir.

Vous pouvez également convertir l’heure dans n’importe quel fuseau horaire désigné en heure locale à l’aide de la static méthode (Shareden Visual Basic). TimeZoneInfo.ConvertTime Cette technique est abordée dans la section suivante.

Conversion entre deux fuseaux horaires

Vous pouvez effectuer une conversion entre deux fuseaux horaires à l’aide de l’une des deux static méthodes suivantes (Shared en Visual Basic) de la TimeZoneInfo classe :

  • ConvertTime

    Les paramètres de cette méthode sont la valeur de date et d’heure à convertir, un TimeZoneInfo objet qui représente le fuseau horaire de la valeur de date et d’heure, et un TimeZoneInfo objet qui représente le fuseau horaire pour convertir la valeur de date et d’heure en.

  • ConvertTimeBySystemTimeZoneId

    Les paramètres de cette méthode sont la valeur de date et d’heure à convertir, l’identificateur du fuseau horaire de la valeur de date et d’heure et l’identificateur du fuseau horaire dans lequel convertir la valeur de date et d’heure.

Les deux méthodes nécessitent que la propriété de la Kind valeur de date et d’heure à convertir et l’identificateur de l’objet ou du TimeZoneInfo fuseau horaire qui représente son fuseau horaire correspondent les uns aux autres. Dans le cas contraire, un ArgumentException est déclenché. Par exemple, si la propriété Kind de la valeur de date et d’heure est DateTimeKind.Local, une exception est levée si l'objet TimeZoneInfo passé en tant que paramètre à la méthode n'est pas égal à TimeZoneInfo.Local. Une exception est également levée si l’identificateur passé en tant que paramètre à la méthode n’est pas égal à TimeZoneInfo.Local.Id.

L’exemple suivant utilise la ConvertTime méthode pour convertir l’heure standard hawaïenne en heure locale :

DateTime hwTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
    TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time");
    Console.WriteLine("{0} {1} is {2} local time.",
            hwTime,
            hwZone.IsDaylightSavingTime(hwTime) ? hwZone.DaylightName : hwZone.StandardName,
            TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local));
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.");
}
Dim hwTime As Date = #2/01/2007 8:00:00 AM#
Try
    Dim hwZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time")
    Console.WriteLine("{0} {1} is {2} local time.", _
                      hwTime, _
                      IIf(hwZone.IsDaylightSavingTime(hwTime), hwZone.DaylightName, hwZone.StandardName), _
                      TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.")
End Try

Conversion des valeurs DateTimeOffset

Les valeurs de date et d’heure représentées par les objets DateTimeOffset ne prennent pas pleinement en compte le fuseau horaire, car elles sont dissociées de celui-ci lors de leur instanciation. Toutefois, dans de nombreux cas, une application doit simplement convertir une date et une heure en fonction de deux décalages différents par rapport à l’heure UTC plutôt qu’à l’heure dans des fuseaux horaires particuliers. Pour effectuer cette conversion, vous pouvez appeler la méthode de l’instance ToOffset actuelle. Le paramètre unique de la méthode est le décalage de la nouvelle valeur de date et d’heure retournée par la méthode.

Par exemple, si la date et l’heure d’une demande d’utilisateur pour une page web sont connues et sérialisées en tant que chaîne au format MM/dd/aaaa hh :mm :ss zzzz, la méthode suivante ReturnTimeOnServer convertit cette valeur de date et d’heure en date et heure sur le serveur web :

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";
   TimeSpan serverOffset = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now);

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = clientTime.ToOffset(serverOffset);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"
    Dim serverOffset As TimeSpan = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now)

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = clientTime.ToOffset(serverOffset)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

Si la méthode passe la chaîne « 9/1/2007 5:32:07 -05:00 », qui représente la date et l’heure dans un fuseau horaire cinq heures antérieures à UTC, elle retourne « 9/1/2007 3:32:07 -07:00 » pour un serveur situé dans le fuseau horaire standard américain.

La classe TimeZoneInfo inclut également une méthode TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) surchargée qui effectue des conversions de fuseau horaire avec des valeurs ToOffset(TimeSpan). Les paramètres de la méthode sont une DateTimeOffset valeur et une référence au fuseau horaire auquel l’heure doit être convertie. L’appel de méthode retourne une DateTimeOffset valeur. Par exemple, la ReturnTimeOnServer méthode de l’exemple précédent peut être réécrite comme suit pour appeler la ConvertTime(DateTimeOffset, TimeZoneInfo) méthode.

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format,
                                  CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = TimeZoneInfo.ConvertTime(clientTime,
                                  TimeZoneInfo.Local);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = TimeZoneInfo.ConvertTime(clientTime, TimeZoneInfo.Local)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

Voir également