Guide pratique pour effectuer un aller-retour de valeurs de date et d’heure

Dans de nombreuses applications, une valeur de date et d’heure est destinée à identifier clairement un point unique dans le temps. Cet article montre comment enregistrer et restaurer une valeur DateTime, une valeur DateTimeOffset et une valeur de date et d’heure avec des informations de fuseau horaire pour que la valeur restaurée identifie la même heure que la valeur enregistrée.

Effectuer un aller-retour d’une valeur DateHeure

  1. Convertissez la valeur DateTime en sa représentation sous forme de chaîne en appelant la méthode DateTime.ToString(String) avec le spécificateur de format « o ».

  2. Enregistrez la représentation sous forme de chaîne de la valeur DateTime dans un fichier ou passez-la dans un processus, un domaine d’application ou une limite d’ordinateur.

  3. Récupérez la chaîne qui représente la valeur DateTime.

  4. Appelez la méthode DateTime.Parse(String, IFormatProvider, DateTimeStyles) et passez DateTimeStyles.RoundtripKind en tant que valeur du paramètre styles.

L’exemple suivant montre comment effectuer un aller-retour d’une valeur DateTime.

const string fileName = @".\DateFile.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTime dateToSave = DateTime.SpecifyKind(new DateTime(2008, 6, 12, 18, 45, 15),
                                           DateTimeKind.Local);
string? dateString = dateToSave.ToString("o");
Console.WriteLine("Converted {0} ({1}) to {2}.",
                  dateToSave.ToString(),
                  dateToSave.Kind.ToString(),
                  dateString);
outFile.WriteLine(dateString);
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName);
outFile.Close();

// Restore DateTime value.
DateTime restoredDate;

using StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();

if (dateString is not null)
{
    restoredDate = DateTime.Parse(dateString, null, DateTimeStyles.RoundtripKind);
    Console.WriteLine("Read {0} ({2}) from {1}.", restoredDate.ToString(),
                                                  fileName,
                                                  restoredDate.Kind.ToString());
}

// The example displays the following output:
//    Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
//    Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
//    Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.
Const fileName As String = ".\DateFile.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As Date = DateTime.SpecifyKind(#06/12/2008 6:45:15 PM#, _
                                              DateTimeKind.Local)
Dim dateString As String = dateToSave.ToString("o")
Console.WriteLine("Converted {0} ({1}) to {2}.", dateToSave.ToString(), _
                  dateToSave.Kind.ToString(), dateString)
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()

' Restore DateTime value.
Dim restoredDate As Date

Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDate = DateTime.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} ({2}) from {1}.", restoredDate.ToString(), _
                  fileName, restoredDAte.Kind.ToString())
' The example displays the following output:
'    Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
'    Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
'    Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.

Durant l’aller-retour d’une valeur DateTime, cette technique permet de conserver correctement l’heure pour toutes les heures locales et universelles. Par exemple, si une valeur DateTime locale est enregistrée sur un système situé dans le fuseau horaire Pacifique (États-Unis) et qu’elle est restaurée sur un système situé dans le fuseau horaire Centre (États-Unis), la date et l’heure restaurées ont deux heures de retard par rapport à l’heure d’origine, ce qui reflète le décalage horaire entre ces deux fuseaux horaires. En revanche, cette technique n’est pas nécessairement exacte pour les heures non spécifiées. Toutes les valeurs DateTime dont la propriété Kind est Unspecified sont traitées comme s’il s’agissait d’heures locales. S’il ne s’agit pas d’une heure locale, DateTime n’identifie pas correctement le bon point dans le temps. La solution pour contourner cette limitation consiste à associer étroitement une valeur de date et d’heure avec son fuseau horaire pour l’opération d’enregistrement et de restauration.

Effectuer un aller-retour d’une valeur DateTimeOffset

  1. Convertissez la valeur DateTimeOffset en sa représentation sous forme de chaîne en appelant la méthode DateTimeOffset.ToString(String) avec le spécificateur de format « o ».

  2. Enregistrez la représentation sous forme de chaîne de la valeur DateTimeOffset dans un fichier ou passez-la dans un processus, un domaine d’application ou une limite d’ordinateur.

  3. Récupérez la chaîne qui représente la valeur DateTimeOffset.

  4. Appelez la méthode DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) et passez DateTimeStyles.RoundtripKind en tant que valeur du paramètre styles.

L’exemple suivant montre comment effectuer un aller-retour d’une valeur DateTimeOffset.

const string fileName = @".\DateOff.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTimeOffset dateToSave = new DateTimeOffset(2008, 6, 12, 18, 45, 15,
                                               new TimeSpan(7, 0, 0));
string? dateString = dateToSave.ToString("o");
Console.WriteLine("Converted {0} to {1}.", dateToSave.ToString(),
                  dateString);
outFile.WriteLine(dateString);
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName);
outFile.Close();

// Restore DateTime value.
DateTimeOffset restoredDateOff;

using StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();

if (dateString is not null)
{
    restoredDateOff = DateTimeOffset.Parse(dateString, null,
                                           DateTimeStyles.RoundtripKind);
    Console.WriteLine("Read {0} from {1}.", restoredDateOff.ToString(), fileName);
}

// The example displays the following output:
//    Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
//    Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
//    Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.
Const fileName As String = ".\DateOff.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As New DateTimeOffset(2008, 6, 12, 18, 45, 15, _
                                     New TimeSpan(7, 0, 0))
Dim dateString As String = dateToSave.ToString("o")
Console.WriteLine("Converted {0} to {1}.", dateToSave.ToString(), dateString)
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()

' Restore DateTime value.
Dim restoredDateOff As DateTimeOffset

Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDateOff = DateTimeOffset.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} from {1}.", restoredDateOff.ToString(), fileName)
' The example displays the following output:
'    Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
'    Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
'    Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.

Cette technique identifie toujours clairement une valeur DateTimeOffset comme point unique dans le temps. La valeur peut ensuite être convertie en temps universel coordonné (UTC) en appelant la méthode DateTimeOffset.ToUniversalTime, ou convertie en heure dans un fuseau horaire particulier en appelant la méthode DateTimeOffset.ToOffset ou TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo). La principale limitation de cette technique est que les opérations arithmétiques de date et heure, effectuées sur une valeur DateTimeOffset qui représente l’heure dans un fuseau horaire particulier, risquent de ne pas produire des résultats exacts pour ce fuseau horaire. En effet, quand une valeur DateTimeOffset est instanciée, elle est dissociée de son fuseau horaire. Ainsi, les règles d’ajustement de ce fuseau horaire ne sont plus applicables quand vous effectuez des calculs de date et d’heure. Vous pouvez contourner ce problème en définissant un type personnalisé qui inclut à la fois une valeur de date et heure et son fuseau horaire correspondant.

Compiler le code

Ces exemples nécessitent que les espaces de noms suivants soient importés avec des directives C# using ou des instructions Visual Basic Imports :

Voir aussi