Tarih ve saatlerle aritmetik işlemler gerçekleştirme

Hem hem de DateTimeDateTimeOffset yapıları değerleri üzerinde aritmetik işlemler gerçekleştiren üyeler sağlasa da, aritmetik işlemlerin sonuçları çok farklıdır. Bu makalede bu farklar incelenir, tarih ve saat verilerindeki saat dilimi farkındalığı dereceleriyle ilişkilendirir ve tarih ve saat verilerini kullanarak tam saat dilimine duyarlı işlemlerin nasıl gerçekleştirilecekleri açıklanır.

DateTime değerleriyle karşılaştırmalar ve aritmetik işlemler

DateTime.Kind özelliği, yerel saati mi, Eşgüdümlü Evrensel Saati (UTC) mi yoksa belirtilmemiş bir saat dilimindeki saati mi temsil ettiğini belirtmek için tarih ve saate bir değer atanmasına olanak tanırDateTimeKind. Ancak, değerlerde tarih ve saat aritmetiği DateTimeKind karşılaştırılırken veya gerçekleştirilirken bu sınırlı saat dilimi bilgileri yoksayılır. Geçerli yerel saati geçerli UTC saatiyle karşılaştıran aşağıdaki örnek, saat dilimi bilgilerinin nasıl yoksayıldığını gösterir.

using System;

public enum TimeComparison
{
   EarlierThan = -1,
   TheSameAs = 0,
   LaterThan = 1
}

public class DateManipulation
{
   public static void Main()
   {
      DateTime localTime = DateTime.Now;
      DateTime utcTime = DateTime.UtcNow;

      Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours",
                        localTime.Kind,
                        utcTime.Kind,
                        (localTime - utcTime).Hours,
                        (localTime - utcTime).Minutes);
      Console.WriteLine("The {0} time is {1} the {2} time.",
                        localTime.Kind,
                        Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)),
                        utcTime.Kind);
   }
}
// If run in the U.S. Pacific Standard Time zone, the example displays
// the following output to the console:
//    Difference between Local and Utc time: -7:0 hours
//    The Local time is EarlierThan the Utc time.
Public Enum TimeComparison As Integer
    EarlierThan = -1
    TheSameAs = 0
    LaterThan = 1
End Enum

Module DateManipulation
    Public Sub Main()
        Dim localTime As Date = Date.Now
        Dim utcTime As Date = Date.UtcNow

        Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours", _
                          localTime.Kind.ToString(), _
                          utcTime.Kind.ToString(), _
                          (localTime - utcTime).Hours, _
                          (localTime - utcTime).Minutes)
        Console.WriteLine("The {0} time is {1} the {2} time.", _
                          localTime.Kind.ToString(), _
                          [Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)), _
                          utcTime.Kind.ToString())
        ' If run in the U.S. Pacific Standard Time zone, the example displays 
        ' the following output to the console:
        '    Difference between Local and Utc time: -7:0 hours
        '    The Local time is EarlierThan the Utc time.                                                    
    End Sub
End Module

CompareTo(DateTime) yöntemi, yerel saatin UTC saatinden (veya daha az) erken olduğunu bildirir ve çıkarma işlemi, ABD Pasifik Standart Saat dilimindeki bir sistem için UTC ile yerel saat arasındaki farkın yedi saat olduğunu gösterir. Ancak bu iki değer tek bir zaman noktasının farklı temsillerini sağladığından, bu durumda zaman aralığının utc'den yerel saat diliminin uzaklığıyla tamamen doğrulanabilir olduğu açıktır.

Daha genel olarak, DateTime.Kind özellik karşılaştırma ve aritmetik yöntemler tarafından Kind döndürülen sonuçları etkilemez (zaman içindeki iki özdeş noktanın karşılaştırılmasında da belirtildiği gibi), ancak bu sonuçların yorumlanmasını etkileyebilir. Örneğin:

  • İki tarih ve saat değeri üzerinde gerçekleştirilen her iki aritmetik işlemin sonucu, her ikisi de eşit DateTimeKind olan DateTime.Kind iki değer arasındaki gerçek zaman aralığını yansıtır. Benzer şekilde, bu tür iki tarih ve saat değerinin karşılaştırılması, saatler arasındaki ilişkiyi doğru şekilde yansıtır.

  • İki tarih ve saat değeri üzerinde gerçekleştirilen aritmetik veya karşılaştırma işleminin sonucu, özellikleri iki tarih ve saat değerine DateTime.Kind eşit DateTimeKind veya farklı DateTime.Kind özellik değerlerine sahip saat değerleri iki değer arasındaki farkı yansıtır.

  • Yerel tarih ve saat değerleri üzerindeki aritmetik veya karşılaştırma işlemleri, belirli bir değerin belirsiz veya geçersiz olup olmadığını dikkate almaz ve yerel saat diliminin yaz saati geçişinin sonucu olan ayarlama kurallarının etkisini dikkate almaz.

  • UTC ile yerel saat arasındaki farkı karşılaştıran veya hesaplayan herhangi bir işlem, sonuçta yerel saat diliminin UTC'den uzaklığıyla eşit bir zaman aralığı içerir.

  • Belirtilmemiş bir saat ile UTC veya yerel saat arasındaki farkı karşılaştıran veya hesaplayan tüm işlemler basit saat saatini yansıtır. Saat dilimi farklılıkları dikkate alınmaz ve sonuç saat dilimi ayarlama kurallarının uygulamasını yansıtmaz.

  • Belirtilmeyen iki saat arasındaki farkı karşılaştıran veya hesaplayan herhangi bir işlem, iki farklı saat dilimindeki saat arasındaki farkı yansıtan bilinmeyen bir aralık içerebilir.

Saat dilimi farklılıklarının tarih ve saat hesaplamalarını etkilemediği birçok senaryo vardır (bu senaryolardan bazılarının tartışması için bkz . DateTime, DateTimeOffset, TimeSpan ve TimeZoneInfo arasında seçim yapma) veya tarih ve saat verilerinin bağlamının karşılaştırma veya aritmetik işlemlerin anlamını tanımlaması.

DateTimeOffset değerleriyle karşılaştırmalar ve aritmetik işlemler

Değer DateTimeOffset yalnızca bir tarih ve saat değil, aynı zamanda UTC'ye göre bu tarih ve saati kesin olarak tanımlayan bir uzaklık da içerir. Bu uzaklık, eşitliği değerlerden DateTime farklı şekilde tanımlamayı mümkün kılar. DateTime Değerler aynı tarih ve saat değerine sahipse eşitken, DateTimeOffset her ikisi de aynı zaman noktasına başvuruda bulunursa değerler eşittir. karşılaştırmalarda ve iki tarih ve saat arasındaki aralığı belirleyen çoğu aritmetik işlemde kullanıldığında, bir DateTimeOffset değer daha doğru ve yoruma daha az ihtiyaç duyar. Yerel ve UTC DateTimeOffset değerlerini karşılaştıran önceki örnekle eşdeğer olan DateTimeOffset aşağıdaki örnek, davranıştaki bu farkı gösterir.

using System;

public enum TimeComparison
{
   EarlierThan = -1,
   TheSameAs = 0,
   LaterThan = 1
}

public class DateTimeOffsetManipulation
{
   public static void Main()
   {
      DateTimeOffset localTime = DateTimeOffset.Now;
      DateTimeOffset utcTime = DateTimeOffset.UtcNow;

      Console.WriteLine("Difference between local time and UTC: {0}:{1:D2} hours",
                        (localTime - utcTime).Hours,
                        (localTime - utcTime).Minutes);
      Console.WriteLine("The local time is {0} UTC.",
                        Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)));
   }
}
// Regardless of the local time zone, the example displays
// the following output to the console:
//    Difference between local time and UTC: 0:00 hours.
//    The local time is TheSameAs UTC.
Public Enum TimeComparison As Integer
    EarlierThan = -1
    TheSameAs = 0
    LaterThan = 1
End Enum

Module DateTimeOffsetManipulation
    Public Sub Main()
        Dim localTime As DateTimeOffset = DateTimeOffset.Now
        Dim utcTime As DateTimeOffset = DateTimeOffset.UtcNow

        Console.WriteLine("Difference between local time and UTC: {0}:{1:D2} hours.", _
                          (localTime - utcTime).Hours, _
                          (localTime - utcTime).Minutes)
        Console.WriteLine("The local time is {0} UTC.", _
                          [Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)))
    End Sub
End Module
' Regardless of the local time zone, the example displays 
' the following output to the console:
'    Difference between local time and UTC: 0:00 hours.
'    The local time is TheSameAs UTC.
'          Console.WriteLine(e.GetType().Name)

Bu örnekte yöntemi, CompareTo geçerli yerel saatle geçerli UTC saatinin eşit olduğunu ve değerlerin CompareTo(DateTimeOffset) çıkarılmasının iki saat arasındaki farkın olduğunu TimeSpan.Zerogösterir.

Değerlerin tarih ve saat aritmetiğinde kullanılmasının DateTimeOffset en önemli sınırlaması, değerlerin DateTimeOffset saat dilimi farkındalığı olsa da tam olarak saat dilimi farkında olmamasıdır. Değerin DateTimeOffset uzaklığı, bir değişkene ilk kez bir değer atandığında DateTimeOffset saat diliminin UTC'den uzaklığını yansıtsa da, bundan sonra saat dilimiyle ilişkilendirilmez hale gelir. Artık tanımlanabilir bir saatle doğrudan ilişkilendirilmediğinden, tarih ve saat aralıklarının eklenmesi ve çıkarılması bir saat dilimi ayarlama kurallarını dikkate almaz.

Abd Orta Standart Saat diliminde yaz saati uygulamasına geçiş, 9 Mart 2008'de saat 02:00'de gerçekleşir. Bunu göz önünde bulundurarak, 9 Mart 2008'de Saat 01:30'da Merkezi Standart saate iki buçuk saatlik bir aralık eklemek, 9 Mart 2008'de saat 05:00'te bir tarih ve saat oluşturmalıdır. Ancak, aşağıdaki örnekte gösterildiği gibi, toplamanın sonucu 9 Mart 2008'de 04:00'tir. Bu işlemin sonucu, ilgilendiğimiz saat dilimindeki saat olmasa da (yani beklenen saat dilimi uzaklığına sahip olmasa da) doğru zaman noktasını temsil eder.

using System;

public class IntervalArithmetic
{
   public static void Main()
   {
      DateTime generalTime = new DateTime(2008, 3, 9, 1, 30, 0);
      const string tzName = "Central Standard Time";
      TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

      // Instantiate DateTimeOffset value to have correct CST offset
      try
      {
         DateTimeOffset centralTime1 = new DateTimeOffset(generalTime,
                    TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime));

         // Add two and a half hours
         DateTimeOffset centralTime2 = centralTime1.Add(twoAndAHalfHours);
         // Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1,
                                                    twoAndAHalfHours.ToString(),
                                                    centralTime2);
      }
      catch (TimeZoneNotFoundException)
      {
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
      }
   }
}
// The example displays the following output to the console:
//    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00
Module IntervalArithmetic
    Public Sub Main()
        Dim generalTime As Date = #03/09/2008 1:30AM#
        Const tzName As String = "Central Standard Time"
        Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

        ' Instantiate DateTimeOffset value to have correct CST offset
        Try
            Dim centralTime1 As New DateTimeOffset(generalTime, _
                       TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime))

            ' Add two and a half hours      
            Dim centralTime2 As DateTimeOffset = centralTime1.Add(twoAndAHalfHours)
            ' Display result
            Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
                                                       twoAndAHalfHours.ToString(), _
                                                       centralTime2)
        Catch e As TimeZoneNotFoundException
            Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
        End Try
    End Sub
End Module
' The example displays the following output to the console:
'    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00

Saat dilimlerindeki saatlerle aritmetik işlemler

sınıfı, TimeZoneInfo saatleri bir saat diliminden diğerine dönüştürdüğünde otomatik olarak ayarlamalar uygulayan dönüştürme yöntemleri içerir. Bu dönüştürme yöntemleri şunlardır:

Ayrıntılar için bkz . Saat dilimleri arasında saatleri dönüştürme.

sınıfı, TimeZoneInfo tarih ve saat aritmetiği gerçekleştirdiğinizde ayarlama kurallarını otomatik olarak uygulayan hiçbir yöntem sağlamaz. Ancak, bir saat dilimindeki saati UTC'ye dönüştürerek, aritmetik işlemi gerçekleştirerek ve ardından UTC'den saat dilimindeki saate dönüştürerek ayarlama kuralları uygulayabilirsiniz. Ayrıntılar için bkz . Nasıl yapılır: Tarih ve saat aritmetiğinde saat dilimlerini kullanma.

Örneğin aşağıdaki kod, 9 Mart 2008'de saat 02:00'ye iki buçuk saat ekleyen önceki koda benzer. Ancak, tarih ve saat aritmetiği gerçekleştirmeden önce Merkezi Standart saati UTC'ye dönüştürdüğünden ve ardından sonucu UTC'den Merkezi Standart saate dönüştürdüğünden, sonuçta elde edilen saat Orta Standart Saat Dilimi'nin yaz saati saatine geçişini yansıtır.

using System;

public class TimeZoneAwareArithmetic
{
   public static void Main()
   {
      const string tzName = "Central Standard Time";

      DateTime generalTime = new DateTime(2008, 3, 9, 1, 30, 0);
      TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
      TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

      // Instantiate DateTimeOffset value to have correct CST offset
      try
      {
         DateTimeOffset centralTime1 = new DateTimeOffset(generalTime,
                                       cst.GetUtcOffset(generalTime));

         // Add two and a half hours
         DateTimeOffset utcTime = centralTime1.ToUniversalTime();
         utcTime += twoAndAHalfHours;

         DateTimeOffset centralTime2 = TimeZoneInfo.ConvertTime(utcTime, cst);
         // Display result
         Console.WriteLine("{0} + {1} hours = {2}", centralTime1,
                                                    twoAndAHalfHours.ToString(),
                                                    centralTime2);
      }
      catch (TimeZoneNotFoundException)
      {
         Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
      }
   }
}
// The example displays the following output to the console:
//    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00
Module TimeZoneAwareArithmetic
    Public Sub Main()
        Const tzName As String = "Central Standard Time"

        Dim generalTime As Date = #03/09/2008 1:30AM#
        Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
        Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

        ' Instantiate DateTimeOffset value to have correct CST offset
        Try
            Dim centralTime1 As New DateTimeOffset(generalTime, _
                       cst.GetUtcOffset(generalTime))

            ' Add two and a half hours 
            Dim utcTime As DateTimeOffset = centralTime1.ToUniversalTime()
            utcTime += twoAndAHalfHours

            Dim centralTime2 As DateTimeOffset = TimeZoneInfo.ConvertTime(utcTime, cst)
            ' Display result
            Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
                                                       twoAndAHalfHours.ToString(), _
                                                       centralTime2)
        Catch e As TimeZoneNotFoundException
            Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
        End Try
    End Sub
End Module
' The example displays the following output to the console:
'    3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00

Ayrıca bkz.