Comment : permettre aux utilisateurs de résoudre des heures ambiguës

Mise à jour : novembre 2007

Une heure ambiguë peut être mappée à plusieurs heures UTC (temps universel coordonné), notamment lorsque l'heure de l'horloge est reculée, comme lors du passage de l'heure d'été à l'heure d'hiver dans un fuseau horaire. Lorsque vous gérez une heure ambiguë, vous pouvez procéder de l'une des manières suivantes :

  • Si l'heure ambiguë est un élément de données entré par l'utilisateur, vous pouvez laisser l'utilisateur résoudre l'ambiguïté.

  • Proposez une méthode de mappage à l'heure UTC. Par exemple, vous pouvez supposer qu'une heure ambiguë est toujours exprimée en heure d'hiver du fuseau horaire.

Cette rubrique indique comment permettre à un utilisateur de résoudre une heure ambiguë.

Pour permettre à un utilisateur de résoudre une heure ambiguë

  1. Obtenez la date et l'heure entrées par l'utilisateur.

  2. Appelez la méthode IsAmbiguousTime pour déterminer si l'heure est ambiguë.

  3. Si l'heure est ambiguë, appelez la méthode GetAmbiguousTimeOffsets pour récupérer un tableau d'objets TimeSpan. Chaque élément du tableau contient un offset UTC auquel l'heure ambiguë peut être mappée.

  4. Laissez l'utilisateur sélectionner l'offset désiré.

  5. Calculez la date et l'heure UTC en soustrayant l'offset sélectionné par l'utilisateur de l'heure locale.

  6. Appelez la méthode static (Shared dans Visual Basic .NET) SpecifyKind pour affecter la valeur DateTimeKind.Utc à la propriété Kind de la valeur de date et d'heure UTC.

Exemple

L'exemple suivant invite l'utilisateur à entrer une date et une heure et, si cette dernière est ambiguë, lui permet de sélectionner l'heure UTC à laquelle l'heure ambiguë est mappée.

Private Sub GetUserDateInput()
   ' Get date and time from user
   Dim inputDate As Date = GetUserDateTime()
   Dim utcDate As Date

   ' Exit if date has no significant value
   If inputDate = Date.MinValue Then Exit Sub

   If TimeZoneInfo.Local.IsAmbiguousTime(inputDate) Then
      Console.WriteLine("The date you've entered is ambiguous.")
      Console.WriteLine("Please select the correct offset from Universal Coordinated Time:")
      Dim offsets() As TimeSpan = TimeZoneInfo.Local.GetAmbiguousTimeOffsets(inputDate)
      For ctr As Integer = 0 to offsets.Length - 1
         Dim zoneDescription As String
         If offsets(ctr).Equals(TimeZoneInfo.Local.BaseUtcOffset) Then 
            zoneDescription = TimeZoneInfo.Local.StandardName
         Else
            zoneDescription = TimeZoneInfo.Local.DaylightName
         End If
         Console.WriteLine("{0}.) {1} hours, {2} minutes ({3})", _
                           ctr, offsets(ctr).Hours, offsets(ctr).Minutes, zoneDescription)
      Next         
      Console.Write("> ")
      Dim selection As Integer = CInt(Console.ReadLine())

      ' Convert local time to UTC, and set Kind property to DateTimeKind.Utc
      utcDate = Date.SpecifyKind(inputDate - offsets(selection), DateTimeKind.Utc)

      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString())
   Else
      utcDate = inputDate.ToUniversalTime()
      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString())    
   End If
End Sub

Private Function GetUserDateTime() As Date
   Dim exitFlag As Boolean = False            ' flag to exit loop if date is valid
   Dim dateString As String 
   Dim inputDate As Date = Date.MinValue

   Console.Write("Enter a local date and time: ")
   Do While Not exitFlag
      dateString = Console.ReadLine()
      If dateString.ToUpper = "E" Then exitFlag = True
      If Date.TryParse(dateString, inputDate) Then
         exitFlag = true
      Else   
         Console.Write("Enter a valid date and time, or enter 'e' to exit: ")
      End If
   Loop

   Return inputDate        
End Function
private void GetUserDateInput()
{
   // Get date and time from user
   DateTime inputDate = GetUserDateTime();
   DateTime utcDate;

   // Exit if date has no significant value
   if (inputDate == DateTime.MinValue) return;

   if (TimeZoneInfo.Local.IsAmbiguousTime(inputDate))
   {
      Console.WriteLine("The date you've entered is ambiguous.");
      Console.WriteLine("Please select the correct offset from Universal Coordinated Time:");
      TimeSpan[] offsets = TimeZoneInfo.Local.GetAmbiguousTimeOffsets(inputDate);
      for (int ctr = 0; ctr < offsets.Length; ctr++)
      {
         Console.WriteLine("{0}.) {1} hours, {2} minutes", ctr, offsets[ctr].Hours, offsets[ctr].Minutes);
      }
      Console.Write("> ");
      int selection = Convert.ToInt32(Console.ReadLine());

      // Convert local time to UTC, and set Kind property to DateTimeKind.Utc
      utcDate = DateTime.SpecifyKind(inputDate - offsets[selection], DateTimeKind.Utc);

      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString());
   }
   else
   {
      utcDate = inputDate.ToUniversalTime();
      Console.WriteLine("{0} local time corresponds to {1} {2}.", inputDate, utcDate, utcDate.Kind.ToString());    
   }
}

private DateTime GetUserDateTime() 
{
   bool exitFlag = false;             // flag to exit loop if date is valid
   string dateString;  
   DateTime inputDate = DateTime.MinValue;

   Console.Write("Enter a local date and time: ");
   while (! exitFlag)
   {
      dateString = Console.ReadLine();
      if (dateString.ToUpper() == "E")
         exitFlag = true;

      if (DateTime.TryParse(dateString, out inputDate))
         exitFlag = true;
      else
         Console.Write("Enter a valid date and time, or enter 'e' to exit: ");
   }

   return inputDate;        
}

La partie principale de l'exemple de code utilise un tableau d'objets TimeSpan pour indiquer les offsets possibles de l'heure ambiguë par rapport à l'heure UTC. Toutefois, ces offsets ne seront probablement pas explicites pour l'utilisateur. Pour clarifier leur signification, le code note également si un offset représente l'heure d'hiver du fuseau horaire local ou son heure d'été. Le code détermine l'heure d'hiver et l'heure d'été en comparant l'offset avec la valeur de la propriété BaseUtcOffset. Cette propriété indique la différence entre l'heure UTC et l'heure d'hiver du fuseau horaire.

Dans cet exemple, toutes les références au fuseau horaire local sont faites via la propriété TimeZoneInfo.Local ; le fuseau horaire local n'est jamais assigné à une variable objet. Il est recommandé d'utiliser cette méthode, car un appel à la méthode TimeZoneInfo.ClearCachedData invalide les objets auxquels le fuseau horaire local est assigné.

Compilation du code

Cet exemple nécessite :

  • qu'une référence à System.Core.dll soit ajoutée au projet ;

  • que l'espace de noms System soit importé avec l'instruction using (requise en code C#).

Voir aussi

Tâches

Comment : résoudre des heures ambiguës

Autres ressources

Heures et fuseaux horaires