Nasıl yapılır: Tarih ve saat aritmetiğinde saat dilimlerini kullanma

Normalde, veya DateTimeOffset değerlerini kullanarak DateTime tarih ve saat aritmetiği gerçekleştirdiğinizde, sonuç herhangi bir saat dilimi ayarlama kuralını yansıtmaz. Tarih ve saat değerinin saat dilimi açıkça tanımlanabilir olduğunda bile (örneğin, Kind özelliği olarak Localayarlandığında) bu durum geçerlidir. Bu konu, belirli bir saat dilimine ait tarih ve saat değerlerinde aritmetik işlemlerin nasıl gerçekleştirildiğini gösterir. Aritmetik işlemlerin sonuçları, saat diliminin ayarlama kurallarını yansıtır.

Ayarlama kurallarını tarih ve saat aritmetiğine uygulamak için

  1. Bir tarih ve saat değerini ait olduğu saat dilimiyle yakından eşleştirmek için bazı yöntemler uygulayın. Örneğin, hem tarih ve saat değerini hem de saat dilimini içeren bir yapı bildirin. Aşağıdaki örnek, bir DateTime değeri saat dilimine bağlamak için bu yaklaşımı kullanır.

    // Define a structure for DateTime values for internal use only
    internal struct TimeWithTimeZone
    {
       TimeZoneInfo TimeZone;
       DateTime Time;
    }
    
    ' Define a structure for DateTime values for internal use only
    Friend Structure TimeWithTimeZone
        Dim TimeZone As TimeZoneInfo
        Dim Time As Date
    End Structure
    
  2. yöntemini veya yöntemini çağırarak ConvertTimeToUtc bir saati Eşgüdümlü Evrensel Saat'e (UTC) dönüştürün ConvertTime .

  3. Aritmetik işlemi UTC saatinde gerçekleştirin.

  4. yöntemini çağırarak saati UTC'den özgün saatin ilişkili saat dilimine dönüştürün TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo) .

Örnek

Aşağıdaki örnek, 9 Mart 2008 saat 01:30 Merkezi Standart Saati'ne iki saat otuz dakika ekler. Saat diliminin yaz saati geçişi otuz dakika sonra, 9 Mart 2008'de saat 02:00'de gerçekleşir. Örnek, önceki bölümde listelenen dört adımı izlediğinden, 9 Mart 2008'de elde edilen süreyi doğru bir şekilde 05:00 olarak bildirir.

using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTime Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTime time)
   {
      if (tz == null)
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(this.Time, this.TimeZone);
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime,
                              TimeZoneInfo.Utc, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

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

         cstTime1 = new TimeZoneTime(cst, time1);
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time,
                                                    twoAndAHalfHours.ToString(),
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}
Public Structure TimeZoneTime
    Public TimeZone As TimeZoneInfo
    Public Time As Date

    Public Sub New(tz As TimeZoneInfo, time As Date)
        If tz Is Nothing Then _
           Throw New ArgumentNullException("The time zone cannot be a null reference.")

        Me.TimeZone = tz
        Me.Time = time
    End Sub

    Public Function AddTime(interval As TimeSpan) As TimeZoneTime
        ' Convert time to UTC
        Dim utcTime As DateTime = TimeZoneInfo.ConvertTimeToUtc(Me.Time, _
                                                                Me.TimeZone)
        ' Add time interval to time
        utcTime = utcTime.Add(interval)
        ' Convert time back to time in time zone
        Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, _
                                TimeZoneInfo.Utc, Me.TimeZone))
    End Function
End Structure

Module TimeArithmetic
    Public Const tzName As String = "Central Standard Time"

    Public Sub Main()
        Try
            Dim cstTime1, cstTime2 As TimeZoneTime

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

            cstTime1 = New TimeZoneTime(cst, time1)
            cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

            Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                       twoAndAHalfHours.ToString(), _
                                                       cstTime2.Time)
        Catch
            Console.WriteLine("Unable to find {0}.", tzName)
        End Try
    End Sub
End Module

Hem hem de DateTimeDateTimeOffset değerler ait olabilecekleri herhangi bir saat dilimiyle ilişkilendirilir. Tarih ve saat aritmetiğini bir saat diliminin ayarlama kurallarını otomatik olarak uygulayacak şekilde gerçekleştirmek için, herhangi bir tarih ve saat değerinin ait olduğu saat dilimi hemen tanımlanabilir olmalıdır. Bu, bir tarih ve saatin ve ilişkili saat diliminin sıkı bir şekilde birleştirilmesi gerektiği anlamına gelir. Bunu yapmanın aşağıdakiler dahil olmak üzere birkaç yolu vardır:

  • Bir uygulamada kullanılan tüm zamanların belirli bir saat dilimine ait olduğunu varsayalım. Bazı durumlarda uygun olsa da, bu yaklaşım sınırlı esneklik ve muhtemelen sınırlı taşınabilirlik sunar.

  • Her ikisini de türün alanları olarak ekleyerek bir tarih ve saati ilişkili saat dilimiyle sıkı bir şekilde eşleştiren bir tür tanımlayın. Bu yaklaşım, tarih ve saat ile saat dilimini iki üye alanında depolamak için bir yapı tanımlayan kod örneğinde kullanılır.

Örnekte, değerler üzerinde DateTime aritmetik işlemlerin nasıl gerçekleştirilerek saat dilimi ayarlama kurallarının sonucu uygulanması gösterilmektedir. Ancak, DateTimeOffset değerler de aynı şekilde kolayca kullanılabilir. Aşağıdaki örnekte, özgün örnekteki kodun değerler yerine DateTime kullanılacak DateTimeOffset şekilde nasıl uyarlanmış olabileceği gösterilmektedir.

using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTimeOffset Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTimeOffset time)
   {
      if (tz == null)
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTimeOffset utcTime = TimeZoneInfo.ConvertTime(this.Time, TimeZoneInfo.Utc);
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

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

         cstTime1 = new TimeZoneTime(cst,
                        new DateTimeOffset(time1, cst.GetUtcOffset(time1)));
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time,
                                                    twoAndAHalfHours.ToString(),
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}
Public Structure TimeZoneTime
    Public TimeZone As TimeZoneInfo
    Public Time As DateTimeOffset

    Public Sub New(tz As TimeZoneInfo, time As DateTimeOffset)
        If tz Is Nothing Then _
           Throw New ArgumentNullException("The time zone cannot be a null reference.")

        Me.TimeZone = tz
        Me.Time = time
    End Sub

    Public Function AddTime(interval As TimeSpan) As TimeZoneTime
        ' Convert time to UTC
        Dim utcTime As DateTimeOffset = TimeZoneInfo.ConvertTime(Me.Time, TimeZoneInfo.Utc)
        ' Add time interval to time
        utcTime = utcTime.Add(interval)
        ' Convert time back to time in time zone
        Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, Me.TimeZone))
    End Function
End Structure

Module TimeArithmetic
    Public Const tzName As String = "Central Standard Time"

    Public Sub Main()
        Try
            Dim cstTime1, cstTime2 As TimeZoneTime

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

            cstTime1 = New TimeZoneTime(cst, _
                           New DateTimeOffset(time1, cst.GetUtcOffset(time1)))
            cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

            Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                       twoAndAHalfHours.ToString(), _
                                                       cstTime2.Time)
        Catch
            Console.WriteLine("Unable to find {0}.", tzName)
        End Try
    End Sub
End Module

Bu toplama işlemi yalnızca değeri UTC'ye dönüştürmeden gerçekleştiriliyorsa DateTimeOffset , sonucun doğru zaman noktasını yansıttığını, ancak uzaklığının o saat için belirlenen saat dilimini yansıtmadığını unutmayın.

Kod derleme

Bu örnek şunları gerektirir:

  • Ad alanının System deyimiyle içeri aktarılması ( using C# kodunda gereklidir).

Ayrıca bkz.