Sdílet prostřednictvím


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ámkaPozná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

DateTimeKind.Local

Převede místní čas na čas UTC.

DateTimeKind.Unspecified

Předpokládá, že parametr dateTime je místního času a převede místní čas na čas UTC.

DateTimeKind.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ámkaPozná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:

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:

  • ConvertTime

    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.

  • ConvertTimeBySystemTimeZoneId

    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

TimeZoneInfo

Koncepty

Zjištění časových pásem definovaných na místním systému

Další zdroje

Data, časy a časových pásem