Comment : 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. Cette rubrique indique comment enregistrer et restaurer une valeur DateTime, une valeur DateTimeOffset et une valeur de date et d'heure avec des informations de fuseau horaire afin que la valeur restaurée identifie la même heure que la valeur enregistrée.
Pour effectuer un aller-retour d'une valeur DateTime
Convertissez la valeur DateTime en représentation sous forme de chaîne en appelant la méthode DateTime.ToString(String) avec le spécificateur de format "o".
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.
Récupérez la chaîne qui représente la valeur DateTime.
Appelez la méthode DateTime.Parse(String, IFormatProvider, DateTimeStyles) et passez DateTimeStyles.RoundtripKind comme valeur du paramètre styles.
L'exemple suivant montre comment effectuer un aller-retour d'une valeur DateTime.
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.
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;
StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();
inFile.Close();
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.
Lorsque vous effectuez un aller-retour d'une valeur DateTime, cette technique conserve l'heure pour toutes les heures locales et universelles. Par exemple, si une valeur DateTime locale est enregistrée sur un système dans le fuseau horaire de la zone Pacifique des États-Unis et est restauré sur un système dans le fuseau horaire du Centre des États-Unis, les date et heure restaurées seront en retard de deux heures par rapport à l'heure d'origine, qui reflète la différence de temps entre les deux fuseaux horaires. Toutefois, 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 des heures locales. Si ce n'est pas le cas, le DateTime n'identifiera pas le point correct dans le temps. Vous pouvez contourner cette limitation en associant étroitement une valeur de date et d'heure à son fuseau horaire pour l'enregistrement et la restauration.
Pour effectuer un aller-retour d'une valeur DateTimeOffset
Convertissez la valeur DateTimeOffset en représentation sous forme de chaîne en appelant la méthode DateTimeOffset.ToString(String) avec le spécificateur de format "o".
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.
Récupérez la chaîne qui représente la valeur DateTimeOffset.
Appelez la méthode DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) et passez DateTimeStyles.RoundtripKind comme valeur du paramètre styles.
L'exemple suivant montre comment effectuer un aller-retour d'une valeur DateTimeOffset.
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.
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;
StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();
inFile.Close();
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.
Cette technique identifie toujours clairement une valeur DateTimeOffset comme point unique dans le temps. La valeur peut ensuite être convertie en temps universel en appelant la méthode DateTimeOffset.ToUniversalTime, ou elle peut être convertie en heure d'un fuseau horaire particulier en appelant la méthode DateTimeOffset.ToOffset ou TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo). La limitation majeure de cette technique est que l'arithmétique de date et d'heure, lorsqu'elle est effectuée sur une valeur DateTimeOffset qui représente l'heure d'un fuseau horaire particulier, est susceptible de ne pas produire de résultats exacts pour ce fuseau horaire. En effet, lorsqu'une valeur DateTimeOffset est instanciée, elle est dissociée de son fuseau horaire. Par conséquent, les règles d'ajustement de ce fuseau horaire ne peuvent plus être appliquées lorsque vous effectuez des calculs de date et d'heure. Vous pouvez contourner ce problème en définissant un type personnalisé qui inclut une valeur de date et d'heure et son fuseau horaire.
Pour effectuer un aller-retour d'une valeur de date et d'heure avec son fuseau horaire
Définissez une classe ou une structure avec deux champs. Le premier champ est un objet DateTime ou DateTimeOffset, et le second est un objet TimeZoneInfo. L'exemple suivant est une version simple de ce type.
<Serializable> Public Class DateInTimeZone Private tz As TimeZoneInfo Private thisDate As DateTimeOffset Public Sub New() End Sub Public Sub New(date1 As DateTimeOffset, timeZone As TimeZoneInfo) If timeZone Is Nothing Then Throw New ArgumentNullException("The time zone cannot be null.") End If Me.thisDate = date1 Me.tz = timeZone End Sub Public Property DateAndTime As DateTimeOffset Get Return Me.thisDate End Get Set If Value.Offset <> Me.tz.GetUtcOffset(Value) Then Me.thisDate = TimeZoneInfo.ConvertTime(Value, tz) Else Me.thisDate = Value End If End Set End Property Public ReadOnly Property TimeZone As TimeZoneInfo Get Return tz End Get End Property End Class
[Serializable] public class DateInTimeZone { private TimeZoneInfo tz; private DateTimeOffset thisDate; public DateInTimeZone() {} public DateInTimeZone(DateTimeOffset date, TimeZoneInfo timeZone) { if (timeZone == null) throw new ArgumentNullException("The time zone cannot be null."); this.thisDate = date; this.tz = timeZone; } public DateTimeOffset DateAndTime { get { return this.thisDate; } set { if (value.Offset != this.tz.GetUtcOffset(value)) this.thisDate = TimeZoneInfo.ConvertTime(value, tz); else this.thisDate = value; } } public TimeZoneInfo TimeZone { get { return this.tz; } } }
Marquez la classe avec l'attribut SerializableAttribute.
Sérialisez l'objet en utilisant la méthode BinaryFormatter.Serialize.
Restaurez l'objet en utilisant la méthode Deserialize.
Effectuez un cast (en C#) ou convertissez (en Visual Basic) l'objet désérialisé en un objet du type approprié.
L'exemple suivant illustre comment effectuer un aller-retour d'un objet qui stocke des informations de date et d'heure et des informations de fuseau horaire.
Const fileName As String = ".\DateWithTz.dat"
Dim tempDate As Date = #9/3/2008 7:00:00 PM#
Dim tempTz As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
Dim dateWithTz As New DateInTimeZone(New DateTimeOffset(tempDate, _
tempTz.GetUtcOffset(tempDate)), _
tempTz)
' Store DateInTimeZone value to a file
Dim outFile As New FileStream(fileName, FileMode.Create)
Try
Dim formatter As New BinaryFormatter()
formatter.Serialize(outFile, dateWithTz)
Console.WriteLine("Saving {0} {1} to {2}", dateWithTz.DateAndTime, _
IIf(dateWithTz.TimeZone.IsDaylightSavingTime(dateWithTz.DateAndTime), _
dateWithTz.TimeZone.DaylightName, dateWithTz.TimeZone.DaylightName), _
fileName)
Catch e As SerializationException
Console.WriteLine("Unable to serialize time data to {0}.", fileName)
Finally
outFile.Close()
End Try
' Retrieve DateInTimeZone value
If File.Exists(fileName) Then
Dim inFile As New FileStream(fileName, FileMode.Open)
Dim dateWithTz2 As New DateInTimeZone()
Try
Dim formatter As New BinaryFormatter()
dateWithTz2 = DirectCast(formatter.Deserialize(inFile), DateInTimeZone)
Console.WriteLine("Restored {0} {1} from {2}", dateWithTz2.DateAndTime, _
IIf(dateWithTz2.TimeZone.IsDaylightSavingTime(dateWithTz2.DateAndTime), _
dateWithTz2.TimeZone.DaylightName, dateWithTz2.TimeZone.DaylightName), _
fileName)
Catch e As SerializationException
Console.WriteLine("Unable to retrieve date and time information from {0}", _
fileName)
Finally
inFile.Close
End Try
End If
' This example displays the following output to the console:
' Saving 9/3/2008 7:00:00 PM -05:00 Central Daylight Time to .\DateWithTz.dat
' Restored 9/3/2008 7:00:00 PM -05:00 Central Daylight Time from .\DateWithTz.dat
const string fileName = @".\DateWithTz.dat";
DateTime tempDate = new DateTime(2008, 9, 3, 19, 0, 0);
TimeZoneInfo tempTz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateInTimeZone dateWithTz = new DateInTimeZone(new DateTimeOffset(tempDate,
tempTz.GetUtcOffset(tempDate)),
tempTz);
// Store DateInTimeZone value to a file
FileStream outFile = new FileStream(fileName, FileMode.Create);
try
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(outFile, dateWithTz);
Console.WriteLine("Saving {0} {1} to {2}", dateWithTz.DateAndTime,
dateWithTz.TimeZone.IsDaylightSavingTime(dateWithTz.DateAndTime) ?
dateWithTz.TimeZone.DaylightName : dateWithTz.TimeZone.DaylightName,
fileName);
}
catch (SerializationException)
{
Console.WriteLine("Unable to serialize time data to {0}.", fileName);
}
finally
{
outFile.Close();
}
// Retrieve DateInTimeZone value
if (File.Exists(fileName))
{
FileStream inFile = new FileStream(fileName, FileMode.Open);
DateInTimeZone dateWithTz2 = new DateInTimeZone();
try
{
BinaryFormatter formatter = new BinaryFormatter();
dateWithTz2 = formatter.Deserialize(inFile) as DateInTimeZone;
Console.WriteLine("Restored {0} {1} from {2}", dateWithTz2.DateAndTime,
dateWithTz2.TimeZone.IsDaylightSavingTime(dateWithTz2.DateAndTime) ?
dateWithTz2.TimeZone.DaylightName : dateWithTz2.TimeZone.DaylightName,
fileName);
}
catch (SerializationException)
{
Console.WriteLine("Unable to retrieve date and time information from {0}",
fileName);
}
finally
{
inFile.Close();
}
}
// This example displays the following output to the console:
// Saving 9/3/2008 7:00:00 PM -05:00 Central Daylight Time to .\DateWithTz.dat
// Restored 9/3/2008 7:00:00 PM -05:00 Central Daylight Time from .\DateWithTz.dat
Cette technique doit toujours refléter clairement le point correct dans le temps avant et après son enregistrement et sa restauration, à condition que l'implémentation de la date et heure et de l'objet de fuseau horaire n'autorise pas la désynchronisation de la valeur de date avec la valeur de fuseau horaire.
Compilation du code
Ces exemples nécessitent :
que les espaces de noms suivants soient importés avec des instructions using C# ou des instructions Imports Visual Basic :
Référence à System.Core.dll.
Chaque exemple de code, autre que la classe DateInTimeZone, doit être inclus dans une classe ou un module Visual Basic, encapsulé dans des méthodes, et appelé par la méthode Main.
Voir aussi
Concepts
Exécution d'opérations de mise en forme