Tijden tussen tijdzones converteren

Het wordt steeds belangrijker voor elke toepassing die werkt met datums en tijden om verschillen tussen tijdzones af te handelen. Een toepassing kan niet langer aannemen dat alle tijden kunnen worden uitgedrukt in de lokale tijd, wat de tijd is die beschikbaar is vanuit de DateTime structuur. Een webpagina die bijvoorbeeld de huidige tijd weergeeft in het oostelijke deel van de Verenigde Staten heeft geen geloofwaardigheid voor een klant in Oost-Azië. In dit artikel wordt uitgelegd hoe u tijden van de ene tijdzone naar een andere converteert en waarden converteert DateTimeOffset met beperkte tijdzonebewustzijn.

Converteren naar Coordinated Universal Time

Coordinated Universal Time (UTC) is een standaard met hoge precisie, atomische tijd. De tijdzones van de wereld worden uitgedrukt als positieve of negatieve verschuivingen van UTC. UTC biedt dus een vrije tijdzone of tijdzoneneutrale tijd. Het gebruik van UTC wordt aanbevolen wanneer de overdraagbaarheid van een datum en tijd op computers belangrijk is. Zie Aanbevolen procedures voor coderen met dateTime in .NET Framework voor meer informatie en andere aanbevolen procedures voor het gebruik van datums en tijden. Het converteren van afzonderlijke tijdzones naar UTC maakt tijdvergelijkingen eenvoudig.

Notitie

U kunt ook een DateTimeOffset structuur serialiseren om een enkel tijdstip ondubbelzinnig weer te geven. Omdat DateTimeOffset objecten een datum- en tijdwaarde samen met de offset van UTC opslaan, vertegenwoordigen ze altijd een bepaald tijdstip ten opzichte van UTC.

De eenvoudigste manier om een tijd te converteren naar UTC is door de static methode (Shared in Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime) aan te roepen. De exacte conversie die door de methode wordt uitgevoerd, is afhankelijk van de waarde van de eigenschap van de dateTime parameter Kind , zoals in de volgende tabel wordt weergegeven:

DateTime.Kind Conversie
DateTimeKind.Local Converteert lokale tijd naar UTC.
DateTimeKind.Unspecified Hiermee wordt ervan uitgegaan dat de dateTime parameter lokale tijd is en dat de lokale tijd wordt geconverteerd naar UTC.
DateTimeKind.Utc Retourneert de dateTime parameter ongewijzigd.

Met de volgende code wordt de huidige lokale tijd geconverteerd naar UTC en wordt het resultaat weergegeven in de console:

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))

Als de datum- en tijdwaarde niet de lokale tijd of UTC vertegenwoordigt, retourneert de ToUniversalTime methode waarschijnlijk een onjuist resultaat. U kunt de TimeZoneInfo.ConvertTimeToUtc methode echter gebruiken om de datum en tijd uit een opgegeven tijdzone te converteren. Zie De tijdzones zoeken die zijn gedefinieerd op een lokaal systeem voor meer informatie over het ophalen van een TimeZoneInfo object dat de doeltijdzone vertegenwoordigt. In de volgende code wordt de TimeZoneInfo.ConvertTimeToUtc methode gebruikt om Eastern Standard Time te converteren naar 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

De TimeZoneInfo.ConvertTimeToUtc methode genereert een ArgumentException als de eigenschap van Kind het DateTime object en de tijdzone niet overeenkomen. Er komt een onjuiste overeenkomst op als de eigenschap isDateTimeKind.Local, maar het TimeZoneInfo object niet de lokale tijdzone vertegenwoordigt, of als de Kind eigenschap is DateTimeKind.Utc maar het TimeZoneInfo object niet gelijk isTimeZoneInfo.Utc.Kind

Al deze methoden nemen DateTime waarden als parameters en retourneren een DateTime waarde. Voor DateTimeOffset waarden heeft de DateTimeOffset structuur een ToUniversalTime exemplaarmethode waarmee de datum en tijd van het huidige exemplaar worden geconverteerd naar UTC. In het volgende voorbeeld wordt de ToUniversalTime methode aangeroepen om een lokale tijd en verschillende andere keren te converteren naar 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   

UTC converteren naar een aangewezen tijdzone

Als u UTC wilt converteren naar lokale tijd, raadpleegt u de sectie UTC converteren naar lokale tijd die volgt. Als u UTC wilt converteren naar de tijd in een tijdzone die u aanwijst, roept u de ConvertTimeFromUtc methode aan. De methode heeft twee parameters:

  • De UTC die moet worden geconverteerd. Dit moet een DateTime waarde zijn waarvan Kind de eigenschap is ingesteld op Unspecified of Utc.

  • De tijdzone om de UTC te converteren naar.

Met de volgende code wordt UTC geconverteerd naar Central Standard Time:

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

UTC converteren naar lokale tijd

Als u UTC wilt converteren naar lokale tijd, roept u de ToLocalTime methode aan van het DateTime object waarvan u de tijd wilt converteren. Het exacte gedrag van de methode is afhankelijk van de waarde van de eigenschap van het object Kind , zoals in de volgende tabel wordt weergegeven:

DateTime.Kind Conversie
DateTimeKind.Local Retourneert de DateTime waarde ongewijzigd.
DateTimeKind.Unspecified Hiermee wordt ervan uitgegaan dat de DateTime waarde UTC is en dat de UTC wordt geconverteerd naar de lokale tijd.
DateTimeKind.Utc Converteert de DateTime waarde naar lokale tijd.

Notitie

De TimeZone.ToLocalTime methode gedraagt zich identiek aan de DateTime.ToLocalTime methode. Het duurt één parameter, de datum- en tijdwaarde, die moet worden geconverteerd.

U kunt de tijd in elke aangewezen tijdzone ook converteren naar lokale tijd met behulp van de static methode (Sharedin Visual Basic). TimeZoneInfo.ConvertTime Deze techniek wordt in de volgende sectie besproken.

Converteren tussen twee tijdzones

U kunt tussen twee tijdzones converteren met behulp van een van de volgende twee static (Shared in Visual Basic)-methoden van de TimeZoneInfo klasse:

  • ConvertTime

    De parameters van deze methode zijn de datum- en tijdwaarde die moet worden geconverteerd, een TimeZoneInfo object dat de tijdzone van de datum- en tijdwaarde vertegenwoordigt en een TimeZoneInfo object dat de tijdzone vertegenwoordigt waarnaar de datum- en tijdwaarde moet worden geconverteerd.

  • ConvertTimeBySystemTimeZoneId

    De parameters van deze methode zijn de datum- en tijdwaarde die moet worden geconverteerd, de id van de tijdzone van de datum- en tijdwaarde en de id van de tijdzone waarnaar de datum- en tijdwaarde moet worden geconverteerd.

Beide methoden vereisen dat de Kind eigenschap van de datum- en tijdwaarde die moet worden geconverteerd en de TimeZoneInfo object- of tijdzone-id die de tijdzone vertegenwoordigt, overeenkomt met elkaar. Anders wordt er een ArgumentException gegooid. Als de eigenschap van de Kind datum- en tijdwaarde bijvoorbeeld is DateTimeKind.Local, wordt er een uitzondering gegenereerd als het TimeZoneInfo object als parameter aan de methode wordt doorgegeven, niet gelijk is aan TimeZoneInfo.Local. Er wordt ook een uitzondering gegenereerd als de id die als parameter aan de methode wordt doorgegeven, niet gelijk is aan TimeZoneInfo.Local.Id.

In het volgende voorbeeld wordt de ConvertTime methode gebruikt om te converteren van Hawaiiaanse standaardtijd naar lokale tijd:

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

DateTimeOffset-waarden converteren

Datum- en tijdwaarden die door DateTimeOffset objecten worden vertegenwoordigd, zijn niet volledig tijdzonebewust omdat het object is ontkoppeld van de tijdzone op het moment dat het wordt geïnstantieerd. In veel gevallen moet een toepassing echter gewoon een datum en tijd converteren op basis van twee verschillende offsets van UTC in plaats van op tijd in bepaalde tijdzones. Als u deze conversie wilt uitvoeren, kunt u de methode van ToOffset het huidige exemplaar aanroepen. De enkele parameter van de methode is de verschuiving van de nieuwe datum- en tijdwaarde die door de methode wordt geretourneerd.

Als de datum en tijd van een gebruikersaanvraag voor een webpagina bijvoorbeeld bekend is en wordt geserialiseerd als een tekenreeks in de notatie MM/dd/jjjj uu:mm:ss zzzz, converteert de volgende ReturnTimeOnServer methode deze datum- en tijdwaarde naar de datum en tijd op de webserver:

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

Als de methode de tekenreeks '9/1/2007 5:32:07 -05:00' doorgeeft, die de datum en tijd in een tijdzone vertegenwoordigt die vijf uur eerder is dan UTC, wordt '9/1/2007 3:32:07 AM -07:00' geretourneerd voor een server die zich in de zone Us. Pacific Standard Time bevindt.

De TimeZoneInfo klasse bevat ook een overbelasting van de TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) methode waarmee tijdzoneconversies met ToOffset(TimeSpan) waarden worden uitgevoerd. De parameters van de methode zijn een DateTimeOffset waarde en een verwijzing naar de tijdzone waarnaar de tijd moet worden geconverteerd. De methode-aanroep retourneert een DateTimeOffset waarde. De ReturnTimeOnServer methode in het vorige voorbeeld kan bijvoorbeeld als volgt worden herschreven om de ConvertTime(DateTimeOffset, TimeZoneInfo) methode aan te roepen.

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

Zie ook