Konvertera tider mellan tidszoner
Det blir allt viktigare för alla program som fungerar med datum och tider för att hantera skillnader mellan tidszoner. Ett program kan inte längre anta att alla tider kan uttryckas i den lokala tiden, vilket är den tid som är tillgänglig från DateTime strukturen. En webbsida som till exempel visar aktuell tid i den östra delen av USA kommer att sakna trovärdighet för en kund i östra Asien. Den här artikeln beskriver hur du konverterar tider från en tidszon till en annan och konverterar DateTimeOffset värden som har begränsad tidszonsmedvetenhet.
Konvertera till samordnad universell tid
Coordinated Universal Time (UTC) är en atomisk tidsstandard med hög precision. Världens tidszoner uttrycks som positiva eller negativa förskjutningar från UTC. UTC tillhandahåller därför en tidszonsfri eller tidszonsneutral tid. Användning av UTC rekommenderas när ett datum och en tids portabilitet mellan datorer är viktig. Mer information och andra metodtips med datum och tider finns i Metodtips för kodning med DateTime i .NET Framework. Om du konverterar enskilda tidszoner till UTC blir det enkelt att göra tidsjämförelser.
Kommentar
Du kan också serialisera en DateTimeOffset struktur så att den representerar en enskild tidpunkt entydigt. Eftersom DateTimeOffset objekt lagrar ett datum- och tidsvärde tillsammans med dess förskjutning från UTC representerar de alltid en viss tidpunkt i förhållande till UTC.
Det enklaste sättet att konvertera en tid till UTC är att anropa static
metoden (Shared
i Visual Basic). TimeZoneInfo.ConvertTimeToUtc(DateTime) Den exakta konvertering som utförs av metoden beror på värdet för dateTime
parameterns Kind egenskap, som följande tabell visar:
DateTime.Kind |
Konvertering |
---|---|
DateTimeKind.Local |
Konverterar lokal tid till UTC. |
DateTimeKind.Unspecified |
Förutsätter att parametern dateTime är lokal tid och konverterar lokal tid till UTC. |
DateTimeKind.Utc |
Returnerar parametern dateTime oförändrad. |
Följande kod konverterar den aktuella lokala tiden till UTC och visar resultatet för konsolen:
DateTime dateNow = DateTime.Now;
Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(dateNow)} UTC.");
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
TimeZoneInfo.ConvertTimeToUtc(dateNow))
Om datum- och tidsvärdet inte representerar den lokala tiden eller UTC ToUniversalTime returnerar metoden sannolikt ett felaktigt resultat. Du kan dock använda TimeZoneInfo.ConvertTimeToUtc metoden för att konvertera datum och tid från en angiven tidszon. Mer information om hur du hämtar ett TimeZoneInfo objekt som representerar måltidszonen finns i Hitta de tidszoner som definierats i ett lokalt system. Följande kod använder TimeZoneInfo.ConvertTimeToUtc metoden för att konvertera Eastern Standard Time till UTC:
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 {TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)} UTC.");
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine($"Unable to find the {easternZoneId} zone in the registry.");
}
catch (InvalidTimeZoneException)
{
Console.WriteLine($"Registry data on the {easternZoneId} zone has been corrupted.");
}
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
Metoden TimeZoneInfo.ConvertTimeToUtc genererar ett ArgumentException om DateTime objektets Kind egenskap och tidszonen är felmatchad. Ett matchningsfel inträffar om Kind egenskapen är DateTimeKind.Local men TimeZoneInfo objektet inte representerar den lokala tidszonen Kind , eller om egenskapen är DateTimeKind.Utc men TimeZoneInfo objektet inte är lika med TimeZoneInfo.Utc.
Alla dessa metoder tar DateTime värden som parametrar och returnerar ett DateTime värde. För DateTimeOffset värden DateTimeOffset har strukturen en ToUniversalTime instansmetod som konverterar datum och tid för den aktuella instansen till UTC. I följande exempel anropas ToUniversalTime metoden för att konvertera en lokal tid och flera andra gånger till UTC:
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
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
Konvertera UTC till en angiven tidszon
Information om hur du konverterar UTC till lokal tid finns i avsnittet Konvertera UTC till lokal tid som följer. Om du vill konvertera UTC till tiden i en tidszon som du anger anropar ConvertTimeFromUtc du metoden. Metoden tar två parametrar:
UTC som ska konverteras. Detta måste vara ett DateTime värde vars Kind egenskap är inställd på
Unspecified
ellerUtc
.Tidszonen som UTC ska konverteras till.
Följande kod konverterar UTC till central standardtid:
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.");
}
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
Konvertera UTC till lokal tid
Om du vill konvertera UTC till lokal tid anropar ToLocalTime du metoden för objektet DateTime vars tid du vill konvertera. Metodens exakta beteende beror på värdet för objektets Kind egenskap, som följande tabell visar:
DateTime.Kind |
Konvertering |
---|---|
DateTimeKind.Local |
Returnerar värdet DateTime oförändrat. |
DateTimeKind.Unspecified |
Förutsätter att värdet DateTime är UTC och konverterar UTC till lokal tid. |
DateTimeKind.Utc |
Konverterar värdet DateTime till lokal tid. |
Kommentar
Metoden TimeZone.ToLocalTime beter sig identiskt med DateTime.ToLocalTime
metoden. Det krävs en enskild parameter, som är datum- och tidsvärdet, för att konvertera.
Du kan också konvertera tiden i en angiven tidszon till lokal tid med hjälp static
av metoden (Shared
i Visual Basic). TimeZoneInfo.ConvertTime Den här tekniken beskrivs i nästa avsnitt.
Konvertera mellan två tidszoner
Du kan konvertera mellan två tidszoner med någon av följande två static
metoder (Shared
i Visual Basic) i TimeZoneInfo klassen:
-
Den här metodens parametrar är det datum- och tidsvärde som ska konverteras, ett
TimeZoneInfo
objekt som representerar tidszonen för datum- och tidsvärdet och ettTimeZoneInfo
objekt som representerar tidszonen som datum- och tidsvärdet ska konverteras till. -
Den här metodens parametrar är det datum- och tidsvärde som ska konverteras, identifieraren för datum- och tidsvärdets tidszon och identifieraren för tidszonen som datum- och tidsvärdet ska konverteras till.
Båda metoderna kräver att Kind egenskapen för datum- och tidsvärdet konverteras och objektet eller tidszonsidentifieraren som representerar tidszonen TimeZoneInfo motsvarar varandra. Annars kastas en ArgumentException . Om Kind
egenskapen för datum- och tidsvärdet till exempel är DateTimeKind.Local
genereras ett undantag om TimeZoneInfo
objektet som skickas som en parameter till metoden inte är lika med TimeZoneInfo.Local
. Ett undantag utlöses också om identifieraren som skickas som en parameter till metoden inte är lika med TimeZoneInfo.Local.Id
.
I följande exempel används ConvertTime metoden för att konvertera från Hawaiian Standard Time till lokal tid:
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.");
}
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
Konvertera DateTimeOffset-värden
Datum- och tidsvärden som representeras av DateTimeOffset objekt är inte helt tidszonsmedvetna eftersom objektet kopplas från tidszonen när det instansieras. I många fall behöver dock ett program helt enkelt konvertera ett datum och en tid baserat på två olika förskjutningar från UTC i stället för på tid i vissa tidszoner. Om du vill utföra den här konverteringen kan du anropa den aktuella instansens ToOffset metod. Metodens enda parameter är förskjutningen av det nya datum- och tidsvärdet som metoden returnerar.
Om till exempel datum och tid för en användarbegäran för en webbsida är känd och serialiseras som en sträng i formatet MM/dd/ååååå hh:mm:ss zzzz konverterar följande ReturnTimeOnServer
metod det här datum- och tidsvärdet till datum och tid på webbservern:
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;
}
}
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
Om metoden skickar strängen "9/1/2007 5:32:07 -05:00", som representerar datum och tid i en tidszon fem timmar tidigare än UTC, returneras "9/1/2007 3:32:07 AM -07:00" för en server som finns i U.S. Pacific Standard Time-zonen.
Klassen TimeZoneInfo innehåller också en överlagring av metoden TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) som utför tidszonskonverteringar med ToOffset(TimeSpan) värden. Metodens parametrar är ett DateTimeOffset värde och en referens till den tidszon som tiden ska konverteras till. Metodanropet returnerar ett DateTimeOffset värde. Metoden i föregående exempel kan till exempel ReturnTimeOnServer
skrivas om på följande sätt för att anropa ConvertTime(DateTimeOffset, TimeZoneInfo) metoden.
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;
}
}
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