Postupy: Operace round-trip pro hodnoty data a času
V mnoha aplikacích je hodnota data a času určena k jednoznačné identifikaci jednoho bodu v čase. Toto téma ukazuje, jak uložit a obnovit hodnoty DateTime a DateTimeOffset a hodnotu data a času s informací o časovém pásmu tak, aby obnovená hodnota označovala stejnou dobu jako uložena hodnota.
Operace round-trip pro hodnotu DateTime
Převeďte hodnoty DateTime na jejich řetězcovou reprezentaci voláním metody DateTime.ToString(String) se specifikátorem formátu o.
Uložte řetězcovou reprezentaci hodnoty DateTime do souboru nebo ji předejte procesu, doméně aplikace nebo hranici počítače.
Načtěte řetězec, který představuje hodnotu DateTime.
Volejte metodu DateTime.Parse(String, IFormatProvider, DateTimeStyles) a předejte DateTimeStyles.RoundtripKind jako hodnotu parametru styles.
Následující příklad ukazuje, jak použít operaci round-trip pro hodnotu 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.
Při operaci round-trip s hodnotou DateTime tato technika úspěšně zachová čas pro všechny místní a univerzální časy. Například pokud je místní hodnota DateTime uložena v systému standardního tichomořského časového pásmo v USA a je znovu načtena v systému v centrálním standardním časovém pásmu USA, obnovená data a časy budou o dvě hodiny pozdější než původní čas, což odráží časový rozdíl mezi dvěma časovými pásmy. Avšak tento postup není nutně přesný pro nespecifikované časy. Se všemi hodnotami DateTime, jejichž vlastnost Kind je Unspecified, je zacházeno, jako kdyby byly místními časy. Není-li to tento případ, DateTime nebude úspěšně identifikovat správný bod v čase. Řešením pro toto omezení je pevně spojit hodnotu data a času s jejich časovým pásmem pro operace uložení a načtení.
Operace round-trip pro hodnotu DateTimeOffset
Převeďte hodnoty DateTimeOffset na jejich řetězcovou reprezentaci voláním metody DateTimeOffset.ToString(String) se specifikátorem formátu o.
Uložte řetězcovou reprezentaci hodnoty DateTimeOffset do souboru nebo ji předejte procesu, doméně aplikace nebo hranici počítače.
Načtěte řetězec, který představuje hodnotu DateTimeOffset.
Volejte metodu DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) a předejte DateTimeStyles.RoundtripKind jako hodnotu parametru styles.
Následující příklad ukazuje, jak použít operaci round-trip pro hodnotu 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.
Tato technika vždy jednoznačně identifikuje hodnotu DateTimeOffset jako jeden bod v čase. Hodnota pak může být převedena na koordinovaný světový čas (standard UTC) voláním metody DateTimeOffset.ToUniversalTime, nebo může být převedena na čas v určitém časovém pásmu voláním metody DateTimeOffset.ToOffset nebo TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo). Hlavním omezením této techniky je, že aritmetické operace data a času, provedené s hodnotami DateTimeOffset, které představují čas v určitém časovém pásmu, nemusí pro toto časové pásmo poskytovat přesné výsledky. Důvodem je, že při vytváření instance hodnoty DateTimeOffset je zrušeno přidružení k příslušnému časovému pásmu. Proto pravidla úpravy časového pásma nemohou být dále aplikovány při provádění výpočtů s daty a časy. Tento problém můžete obejít definováním vlastního typu, který obsahuje hodnoty data a času a jejich příslušná časová pásma.
Operace round-trip pro hodnoty data a času s jejich časovými pásmy
Definujte třídu nebo strukturu s dvěmi poli. První pole je buď objekt DateTime nebo DateTimeOffset a druhé je objekt TimeZoneInfo. Následující příklad je jednoduchou verzí takového typu.
<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; } } }
Označte třídu atributem SerializableAttribute.
Serializujte objekt pomocí metody BinaryFormatter.Serialize.
Vraťte objekt pomocí metody Deserialize.
Přetypujte (v jazyce C#) nebo převeďte (v jazyce Visual Basic) deserializovaný objekt na objekt vhodného typu.
Následující příklad ukazuje způsob použití operace round-trip pro objekt, který ukládá informaci o datu a čase a informaci o časovém pásmu.
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
Tento postup by měl vždy odrážet jednoznačný bod v čase jak před, tak i po uložení a obnovení, za předpokladu, že implementace kombinovaného objektu data a času a časového pásma nepovoluje hodnotě data, aby přestala být synchronizována s hodnotou časového pásma.
Probíhá kompilace kódu
Tyto příklady vyžadují:
Aby byly imporotvány následující obory názvů příkazy jazyka C# using nebo příkazy Visual Basic Imports:
Odkaz na System.Core.dll.
Každý příklad kódu, jiný než třída DateInTimeZone, by měl být zahrnut do třídy nebo modulu Visual Basic, zabalen do metod a volán z metody Main.