Saatleri saat dilimleri arasında 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 yerel saatle ifade edilebildiğini varsayabilir. Bu, yapıdan DateTime kullanılabilir zamandır. Örneğin, Birleşik Devletler doğu kısmında geçerli saati görüntüleyen bir web sayfası, Doğu Asya'daki bir müşteriye güvenilirlik eksikliği gösterir. 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 bir saat dilimi serbest veya saat dilimi nötr 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.

Not

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üştürme
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öntemiArgumentException, nesnenin DateTimeKind özelliğiyle saat diliminin eşleşmemiş olup olmadığını oluşturur. Özelliğin olması ancak nesnenin yerel saat dilimini temsil etmemesi veya özelliğin DateTimeKind.UtcTimeZoneInfoKind eşit olmaması TimeZoneInfo.Utcdurumunda bir uyuşmazlık oluşur.TimeZoneInfoDateTimeKind.LocalKind

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 birkaç kez daha UTC'ye dönüştürmek için yöntemini çağırır ToUniversalTime :

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'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, özelliği veya Utcolarak ayarlanmış Unspecified bir DateTime değer Kind olmalıdır.

  • UTC'yi dönüştürülecek 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üştürme
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.

Not

yöntemi yöntemiyle TimeZone.ToLocalTimeDateTime.ToLocalTime 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

sınıfının aşağıdaki iki yöntemden birini (SharedVisual Basic'te) TimeZoneInfo kullanarak herhangi bir 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 oluşturulur. Örneğin, tarih ve saat değerinin özelliği ise KindDateTimeKind.Local, yöntemine parametre olarak geçirilen nesne değerine eşit TimeZoneInfo.Localdeğilse TimeZoneInfo bir özel durum oluşturulur. Yöntemine parametre olarak geçirilen tanımlayıcı ile eşit TimeZoneInfo.Local.Iddeğilse bir özel durum da oluşturulur.

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

Nesneler tarafından DateTimeOffset temsil edilen tarih ve saat değerleri tam olarak saat dilimine duyarlı değildir çünkü nesne örneği oluşturulduğu sırada saat dilimiyle ilişkilendirilmez. 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, saat dilimi dönüştürmelerini değerlerle ToOffset(TimeSpan) gerçekleştiren yönteminin aşırı yüklemesini TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) de içerir. Yöntemin parametreleri bir DateTimeOffset değerdir ve saatin dönüştürüldüğü saat dilimine başvurudur. Yöntem çağrısı bir DateTimeOffset değer döndürür. Örneğin, ReturnTimeOnServer önceki örnekteki yöntem, yöntemini çağırmak ConvertTime(DateTimeOffset, TimeZoneInfo) 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.