Aracılığıyla paylaş


Saat dilimleri arasında saatleri dönüştürme

Tarih ve saatlerle çalışan tüm uygulamaların saat dilimleri arasındaki farkları işlemesi giderek daha önemli hale geliyor. Bir uygulama, artık tüm zamanların, DateTime yapısından elde edilen zamanda ifade edilebileceğini varsayamaz. Örneğin, ABD'nin doğu kesiminde geçerli saati görüntüleyen bir web sayfası, Doğu Asya'daki bir müşteri için güvenilir olmayacaktır. Bu makalede, zamanların bir saat diliminden diğerine nasıl dönüştürüldüğü ve sınırlı saat dilimi farkındalığı olan değerlerin nasıl dönüştürüldüğü DateTimeOffset açıklanır.

Eşgüdümlü Evrensel Saate Dönüştürme

Eşgüdümlü Evrensel Saat (UTC), yüksek duyarlıklı, atomik saat standardıdır. Dünyanın saat dilimleri UTC'den pozitif veya negatif uzaklık olarak ifade edilir. Bu nedenle UTC, saat dilimi bağımsız veya saat dilimi açısından tarafsız bir saat sağlar. Bilgisayarlar arasında bir tarih ve saatin taşınabilirliği önemli olduğunda UTC kullanılması önerilir. Tarih ve saatleri kullanan ayrıntılar ve diğer en iyi yöntemler için bkz. .NET Framework'te DateTime kullanarak en iyi yöntemleri kodlama. Tek tek saat dilimlerini UTC'ye dönüştürmek, zaman karşılaştırmalarını kolaylaştırır.

Uyarı

Ayrıca, zaman içinde tek bir noktayı kesin bir şekilde temsil etmek için bir DateTimeOffset yapıyı seri hale getirebilirsiniz. DateTimeOffset Nesneler utc'den uzaklığıyla birlikte bir tarih ve saat değeri depoladığından, her zaman UTC ile ilgili olarak belirli bir noktayı temsil eder.

Saati UTC'ye dönüştürmenin en kolay yolu (Shared Visual Basic'te) TimeZoneInfo.ConvertTimeToUtc(DateTime) yöntemini çağırmaktır static . Yöntemi tarafından gerçekleştirilen tam dönüştürme, aşağıdaki tabloda gösterildiği gibi parametrenin dateTimeKind özelliğinin değerine bağlıdır:

DateTime.Kind Dönüşüm
DateTimeKind.Local Yerel saati UTC'ye dönüştürür.
DateTimeKind.Unspecified parametresinin dateTime yerel saat olduğunu varsayar ve yerel saati UTC'ye dönüştürür.
DateTimeKind.Utc Parametresini dateTime değiştirmeden döndürür.

Aşağıdaki kod geçerli yerel saati UTC'ye dönüştürür ve sonucu konsola görüntüler:

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

Tarih ve saat değeri yerel saati veya UTC'yi temsil etmiyorsa, ToUniversalTime yöntem büyük olasılıkla hatalı bir sonuç döndürür. Ancak, belirtilen bir saat diliminden tarih ve saati dönüştürmek için yöntemini kullanabilirsiniz TimeZoneInfo.ConvertTimeToUtc . Hedef saat dilimini temsil eden bir TimeZoneInfo nesneyi alma hakkında ayrıntılı bilgi için bkz. Yerel sistemde tanımlanan saat dilimlerini bulma. Aşağıdaki kod, Doğu Standart Saati'ni TimeZoneInfo.ConvertTimeToUtc UTC'ye dönüştürmek için yöntemini kullanır:

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

TimeZoneInfo.ConvertTimeToUtc yöntemi, DateTime nesnesinin Kind özelliği ile saat dilimi uyuşmadığında bir ArgumentException fırlatır. Bir uyuşmazlık, Kind özelliği DateTimeKind.Local olduğunda ancak TimeZoneInfo nesnesi yerel saat dilimini temsil etmezse veya Kind özelliği DateTimeKind.Utc olduğunda TimeZoneInfo nesnesi TimeZoneInfo.Utc eşit değilse oluşur.

Bu yöntemlerin tümü değerleri parametre olarak alır DateTime ve bir DateTime değer döndürür. Değerler için DateTimeOffset yapı, DateTimeOffset geçerli örneğin tarih ve saatini UTC'ye dönüştüren bir ToUniversalTime örnek yöntemine sahiptir. Aşağıdaki örnek, yerel saati ve diğer birkaç saati UTC'ye dönüştürmek için ToUniversalTime yöntemini çağırır.

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: {localTime}");
Console.WriteLine();

// Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero);
Console.WriteLine($"Other time: {otherTime}");
Console.WriteLine($"{localTime} = {otherTime}: {localTime.Equals(otherTime)}");
Console.WriteLine($"{localTime} exactly equals {otherTime}: {localTime.EqualsExact(otherTime)}");
Console.WriteLine();

// Convert other time to UTC
universalTime = localTime.ToUniversalTime();
Console.WriteLine($"Universal time: {universalTime}");
Console.WriteLine($"{otherTime} = {universalTime}: {universalTime.Equals(otherTime)}");
Console.WriteLine($"{otherTime} exactly equals {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'yi belirlenen saat dilimine dönüştürme

UTC'yi yerel saate dönüştürmek için aşağıdaki UTC'yi yerel saate dönüştürme bölümüne bakın. UTC'yi belirlediğiniz herhangi bir saat dilimindeki saate dönüştürmek için yöntemini çağırın ConvertTimeFromUtc . yöntemi iki parametre alır:

  • Dönüştürülecek UTC. Bu, Kind özelliği Unspecified veya Utc olarak ayarlanmış bir DateTime değeri olmalıdır.

  • UTC'nin dönüştürüleceği saat dilimi.

Aşağıdaki kod UTC'yi Merkezi Standart Saat'e dönüştürür:

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'yi yerel saate dönüştürme

UTC'yi yerel saate dönüştürmek için, saatini dönüştürmek istediğiniz nesnenin DateTime yöntemini çağırınToLocalTime. Yönteminin tam davranışı, aşağıdaki tabloda gösterildiği gibi nesnenin Kind özelliğinin değerine bağlıdır:

DateTime.Kind Dönüşüm
DateTimeKind.Local DateTime Değeri değiştirmeden döndürür.
DateTimeKind.Unspecified Değerin DateTime UTC olduğunu varsayar ve UTC'yi yerel saate dönüştürür.
DateTimeKind.Utc DateTime Değeri yerel saate dönüştürür.

Uyarı

TimeZone.ToLocalTime yöntemi, DateTime.ToLocalTime yöntemiyle aynı şekilde davranır. Dönüştürmek için tarih ve saat değeri olan tek bir parametre gerekir.

Ayrıca, (Shared Visual Basic'te) TimeZoneInfo.ConvertTime yöntemini kullanarak static belirlenen herhangi bir saat dilimindeki saati yerel saate dönüştürebilirsiniz. Bu teknik sonraki bölümde açıklanmıştır.

herhangi iki saat dilimi arasında dönüştürme

TimeZoneInfo sınıfının iki yönteminden birini (Shared Visual Basic'te) kullanarak herhangi iki static saat dilimi arasında dönüştürme yapabilirsiniz.

  • ConvertTime

    Bu yöntemin parametreleri dönüştürülecek tarih ve saat değeri, TimeZoneInfo tarih ve saat değerinin saat dilimini temsil eden bir TimeZoneInfo nesne ve tarih ve saat değerinin dönüştürüldüğü saat dilimini temsil eden nesnedir.

  • ConvertTimeBySystemTimeZoneId

    Bu yöntemin parametreleri dönüştürülecek tarih ve saat değeri, tarih ve saat değerinin saat dilimi tanımlayıcısı ve tarih ve saat değerinin dönüştürülecek saat dilimi tanımlayıcısıdır.

Her iki yöntem de dönüştürülecek Kind tarih ve saat değerinin özelliğinin ve TimeZoneInfo saat dilimini temsil eden nesnenin veya saat dilimi tanımlayıcısının birbirine karşılık geldiğini gerektirir. Aksi takdirde, bir ArgumentException atılır. Örneğin, tarih ve saat değerinin Kind özelliği DateTimeKind.Local ise, metoda parametre olarak geçirilen TimeZoneInfo nesnesi TimeZoneInfo.Local'e eşit değilse bir istisna fırlatılır. Yöntemine parametre olarak verilen tanımlayıcı TimeZoneInfo.Local.Id ile eşit değilse bir istisna da fırlatılır.

Aşağıdaki örnek, Hawaii Standart Saati'nden yerel saate dönüştürmek için yöntemini kullanır ConvertTime :

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 değerlerini dönüştürme

Tarih ve saat değerleri DateTimeOffset nesneleri tarafından temsil edildiğinde, tam olarak saat dilimi farkındalığına sahip değildir çünkü nesne oluşturulduğu anda saat diliminden ayrıştırılmıştır. Ancak çoğu durumda, bir uygulamanın belirli saat dilimlerindeki saat yerine UTC'den iki farklı uzaklık temelinde bir tarih ve saati dönüştürmesi yeterlidir. Bu dönüştürmeyi gerçekleştirmek için geçerli örneğin ToOffset yöntemini çağırabilirsiniz. Yöntemin tek parametresi, yöntemin döndüreceği yeni tarih ve saat değerinin uzaklığıdır.

Örneğin, bir web sayfası için kullanıcı isteğinin tarih ve saati biliniyorsa ve AA/gg/yy hh:mm:ss zzzz biçiminde bir dize olarak seri hale getiriliyorsa, aşağıdaki ReturnTimeOnServer yöntem bu tarih ve saat değerini web sunucusundaki tarih ve saate dönüştürür:

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

Yöntem UTC'den beş saat önceki bir saat dilimindeki tarih ve saati temsil eden "1/9/2007 5:32:07 -05:00" dizesini geçirirse, ABD Pasifik Standart Saat diliminde bulunan bir sunucu için "1/9/2007 3:32:07 -07:00" değerini döndürür.

Sınıf TimeZoneInfo, ToOffset(TimeSpan) değerleri ile saat dilimi dönüştürmelerini gerçekleştiren TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) metodunun bir aşırı yüklemesini de içermektedir. Yöntemin parametreleri bir DateTimeOffset değeri ve saatin dönüştürüleceği saat dilimine referanstır. Yöntem çağrısı bir DateTimeOffset değer döndürür. Örneğin, önceki örnekteki ReturnTimeOnServer yöntemi, ConvertTime(DateTimeOffset, TimeZoneInfo) yöntemini çağırmak için aşağıdaki gibi yeniden yazılabilir.

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

Ayrıca bkz.