Převod časů mezi časovými pásmy
Zvládnutí rozdílu mezi časovými pásmy se stává stále významnějším pro libovolnou aplikaci, která pracuje s daty a časy. Aplikace již nemůže předpokládat, že všechny časy mohou být vyjádřeny v místním čase, což je čas, který je k dispozici ze struktury DateTime. Například webová stránka, která zobrazí aktuální čas ve východní části USA, nebude působit důvěryhodně pro zákazníka ve východní Asii. Toto téma vysvětluje, jak lze převést časy z jednoho časového pásma na jiné, a také vysvětluje převod hodnot DateTimeOffset, které berou omezený ohled na časové pásmo.
Převod na koordinovaný světový čas
Koordinovaný světový čas (standard UTC) je vysoce přesný standard času dle atomových hodin. Světová časová pásma jsou vyjádřena jako kladný nebo záporný posun od času UTC. Proto čas UTC poskytuje typ času nezávislého nebo neutrálního vzhledem k časovým pásmům. Použití času UTC se doporučuje, když je důležitá přenositelnost data a času mezi počítači. (Podrobnosti a další doporučené postupy pomocí data a časy v kódování nejlepší postupy pomocí DateTime v.NET Framework.) Převod jednotlivých časových pásem na čas UTC usnadňuje porovnávání času.
Poznámka |
---|
Můžete také serializovat strukturu DateTimeOffset pro jednoznačné určení konkrétního bodu v čase. Protože objekty DateTimeOffset ukládají hodnoty data a času spolu s jeho posunem od času UTC, vždy představují konkrétní bod v čase ve vztahu k času UTC. |
Chcete-li převést čas na čas UTC, je nejjednodušší volat metodu static (Shared v jazyce Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime). Přesný převod prováděný metodou závisí na hodnotě dateTime parametru vlastnosti Kind, jak ukazuje následující tabulka.
Vlastnost DateTime.Kind |
Funkce pro převod |
---|---|
Převede místní čas na čas UTC. |
|
Předpokládá, že parametr dateTime je místního času a převede místní čas na čas UTC. |
|
Vrátí parametr dateTime beze změny. |
Následující kód převede aktuální místní čas na čas UTC a výsledek zobrazí v konzole.
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
TimeZoneInfo.ConvertTimeToUtc(dateNow))
DateTime dateNow = DateTime.Now;
Console.WriteLine("The date and time are {0} UTC.",
TimeZoneInfo.ConvertTimeToUtc(dateNow));
Poznámka |
---|
Metoda TimeZoneInfo.ConvertTimeToUtc(DateTime) nutně nevytvoří výsledky, které jsou shodné s metodou TimeZone.ToUniversalTime a DateTime.ToUniversalTime. Jestliže časové pásmo lokálního počítače obsahuje více pravidel úpravy, TimeZoneInfo.ConvertTimeToUtc(DateTime) aplikuje příslušné pravidlo na určité datum a čas. Další dvě metody vždy aplikují nejnovější pravidlo úpravy. |
Pokud hodnota data a času nepředstavuje místní čas nebo čas UTC, metoda ToUniversalTime vrátí pravděpodobně chybný výsledek. Můžete však použít metodu TimeZoneInfo.ConvertTimeToUtc pro převedení data a času ze zadaného časového pásma. (Další informace o načítání objektu TimeZoneInfo, který představuje cílové časové pásmo, naleznete zde: Zjištění časových pásem definovaných na místním systému.) Následující kód používá metodu TimeZoneInfo.ConvertTimeToUtc pro převod východního standardního času na čas UTC.
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
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 {0} UTC.",
TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone));
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("Unable to find the {0} zone in the registry.",
easternZoneId);
}
catch (InvalidTimeZoneException)
{
Console.WriteLine("Registry data on the {0} zone has been corrupted.",
easternZoneId);
}
Všimněte si, že tato metoda vyvolá ArgumentException pokud se vlastnost Kind objektu DateTime a časové pásmo neshodují. Nesoulad nastává, pokud vlastnost Kind je DateTimeKind.Local ale objekt TimeZoneInfo nepředstavuje místní časové pásmo, nebo pokud vlastnost Kind je DateTimeKind.Utc ale objekt TimeZoneInfo není roven DateTimeKind.Utc.
Všechny tyto metody přijmou hodnoty DateTime jako parametry a vrátí hodnotu DateTime. Pro hodnoty DateTimeOffset, struktura DateTimeOffset má instanci metody ToUniversalTime, která převádí datum a čas aktuální instance na čas UTC. V následujícím příkladu je volána metoda ToUniversalTime pro převedení místního času a několika jiných časů na koordinovaný světový čas UTC.
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
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: {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
Převod času UTC do požadovaného časového pásma
Chcete-li převést čas UTC na místní čas, naleznete tyto informace v následující sekci Převod času UTC na místní čas. Pro převod času UTC na čas v jakémkoli časovém pásmu, použijte metodu ConvertTimeFromUtc. Tato metoda přebírá dva parametry:
Čas UTC pro převod. Toto musí být hodnota DateTime jejíž vlastnost Kind je nastavena na DateTimeKind.Utc nebo DateTimeKind.Unspecified.
Časové pásmo do kterého chcete převést čas UTC.
Následující kód převede čas UTC na Centrální standardní čas.
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
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.");
}
Převod času UTC na místní čas
Pro převod času UTC na místní čas použijte metodu ToLocalTime objektu DateTime, jehož čas chcete převést. Přesné chování metody závisí na hodnotě vlastnosti objektu Kind, jak ukazuje následující tabulka.
DateTime.KindVlastnost |
Funkce pro převod |
---|---|
DateTimeKind.Local |
Vrátí hodnotu DateTime beze změny. |
DateTimeKind.Unspecified |
Předpokládá, že hodnota DateTime je čas UTC a převede čas UTC na místní čas. |
DateTimeKind.Utc |
Převede hodnotu DateTime na místní čas. |
Poznámka: Metoda TimeZone.ToLocalTime se chová stejně jako metoda DateTime.ToLocalTime. Přijímá jeden parametr, kterým je hodnota data a času pro převod.
Můžete také převést čas v libovolném požadovaném časovém pásmu na místní čas pomocí metody static (Shared v jazyce Visual Basic) TimeZoneInfo.ConvertTime. Tato technika je popsána v následujícím oddíle.
Převod mezi libovolnými dvěma časovými pásmy
Můžete převádět mezi každými dvěmi časovými pásmy pomocí některé z následujících dvou metod static (Shared v jazyce Visual Basic) třídy TimeZoneInfo:
-
Parametry této metody jsou hodnota data a času, kterou chcete převést, objekt TimeZoneInfo, který představuje časové pásmo pro danou hodnotu data a času a objekt TimeZoneInfo, který představuje cílové časové pásmo pro převod.
-
Parametry této metody jsou hodnota data a času pro převod, identifikátor časového pásma převáděné hodnoty a identifikátor časového pásma cílové hodnoty.
Obě metody požadují, aby vlastnost Kind hodnoty data a času pro převod a objekt TimeZoneInfo nebo příslušný identifikátor časového pásma si navzájem odpovídaly. V opačném případě je vyvolána ArgumentException. Například pokud vlastnost Kind hodnoty data a času je DateTimeKind.Local, je vyvolána výjimka, pokud objekt TimeZoneInfo předaný jako parametr pro metodu není roven TimeZoneInfo.Local. Pokud se identifikátor předáný jako parametr metody nerovná TimeZoneInfo.Local.Id je také vyvolána výjimka.
V následujícím příkladu je použita metoda ConvertTime pro převod z havajského standardního času na místní čas.
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
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.");
}
Převod hodnot DateTimeOffset
Hodnoty data a času reprezentované objekty DateTimeOffset neberou plný ohled na časové pásmo, protože objekt je oddělen od svého časového pásma v ten moment, kdy je vytvořen. Avšak v mnoha případech aplikace jednoduše potřebuje převést datum a čas založený na dvou různých časových posunech od času UTC, než na časech v konkrétních časových pásmech. Chcete-li provést tento převod, můžete zavolat aktuální instanci metody ToOffset. Jediný parametr metody je posun nové hodnoty data a času, kterou má metoda vrátit.
Například pokud je znám datum a čas požadavku uživatele na webovou stránku a je serializován jako řetězec ve formátu MM/dd/rrrr hh:mm:ss zzzz, následující metoda ReturnTimeOnServer převede tuto hodnotu data a času na datum a čas webového serveru.
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
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;
}
}
Pokud je metodě předán řetězec "9/1/2007 5:32:07 -05:00", což představuje datum a čas v časovém pásmu o pět hodin dřívějším než čas UTC, vrátí 9/1/2007 3:32:07 AM -07:00 pro server v tichomořském časovém pásmu USA.
Třída TimeZoneInfo také zahrnuje přetížení metody TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo), která provádí převody časových zón s hodnotami DateTimeOffset. Parametry metody jsou hodnota DateTimeOffset a odkaz na časové pásmo, na které má být čas převeden. Volání metody vrátí hodnotu DateTimeOffset. Například metoda ReturnTimeOnServer v předchozím příkladu by mohla být takto přepsána pro volání metody ConvertTime(DateTimeOffset, TimeZoneInfo).
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
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;
}
}
Viz také
Odkaz
Koncepty
Zjištění časových pásem definovaných na místním systému