Aracılığıyla paylaş


DateTime, DateOnly, DateTimeOffset, TimeSpan, TimeOnly ve TimeZoneInfo arasında seçim yapma

.NET uygulamaları tarih ve saat bilgilerini çeşitli yollarla kullanabilir. Tarih ve saat bilgilerinin daha yaygın kullanım alanları şunlardır:

  • Zaman bilgilerinin önemli olmaması için yalnızca tarihi yansıtmak.
  • Sadece saat bilgisini yansıtmak, böylece tarih bilgisi önemli olmasın.
  • Belirli bir saat ve yere bağlı olmayan soyut bir tarih ve saati yansıtmak için (örneğin, uluslararası bir zincirdeki çoğu mağaza hafta içi 09:00'da açıktır).
  • .NET dışındaki kaynaklardan tarih ve saat bilgilerini almak için, genellikle tarih ve saat bilgilerinin basit bir veri türünde depolandığı durumlarda kullanılır.
  • Zaman içinde tek bir noktayı benzersiz ve net bir şekilde tanımlamak için. Bazı uygulamalar, bir tarih ve saatin yalnızca konak sisteminde belirsiz olmasını gerektirir. Diğer uygulamalar bunun sistemler arasında belirsiz olmasını gerektirir (başka bir deyişle, bir sistemde seri hale getirilmiş bir tarih anlamlı bir şekilde seri durumdan çıkarılabilir ve dünyanın herhangi bir yerinde başka bir sistemde kullanılabilir).
  • birden fazla ilgili zamanı (istek sahibinin yerel saati ve bir web isteği için sunucunun alınma saati gibi) saklamak amacıyla.
  • Tarih ve saat aritmetiği gerçekleştirmek için, büyük olasılıkla tek bir zaman noktasını benzersiz ve kesin olarak tanımlayan bir sonuçla.

.NET DateTime, DateOnly, DateTimeOffset, TimeSpan, TimeOnlyve TimeZoneInfo türlerini içerir. Bunların tümü tarih ve saatlerle çalışan uygulamalar oluşturmak için kullanılabilir.

Dikkat

İşlevselliği neredeyse tamamen TimeZone sınıfına dahil edildiğinden bu makalede TimeZoneInfo ele alınmıyor. Mümkün olduğunda, TimeZoneInfo sınıfı yerine TimeZone sınıfını kullanın.

DateTimeOffset yapısı

DateTimeOffset yapısı, bir tarih ve saat değerini temsil eder ve bu değerin UTC'den ne kadar farklı olduğunu gösteren bir uzaklık ile birlikte. Bu nedenle, değer her zaman zaman tek bir noktayı kesin olarak tanımlar.

DateTimeOffset türü, DateTime türünün tüm işlevlerini ve saat dilimi farkındalığını içerir. Bu, aşağıdaki uygulamalar için uygun hale getirir:

  • Zaman içinde tek bir noktayı benzersiz ve net bir şekilde tanımlayın. DateTimeOffset türü , "now" anlamını kesin olarak tanımlamak, işlem sürelerini günlüğe kaydetmek, sistem veya uygulama olaylarının zamanlarını günlüğe kaydetmek ve dosya oluşturma ve değiştirme sürelerini kaydetmek için kullanılabilir.
  • Genel tarih ve saat aritmetiğini gerçekleştirin.
  • Bu süreler iki ayrı değer veya bir yapının iki üyesi olarak depolandığı sürece, birden çok ilgili zamanı koruyun.

Dikkat

DateTimeOffset değerlerine yönelik bu kullanımlar, DateTime değerlerin kullanımlarından çok daha yaygındır. Sonuç olarak, uygulama geliştirme için varsayılan tarih ve saat türü olarak DateTimeOffset düşünün.

DateTimeOffset değeri belirli bir saat dilimine bağlı değildir, ancak çeşitli saat dilimlerinden kaynaklanabilir. Aşağıdaki örnek, bir dizi DateTimeOffset değerinin (yerel Pasifik Standart Saati dahil) ait olabileceği saat dilimlerini listeler.

using System;
using System.Collections.ObjectModel;

public class TimeOffsets
{
    public static void Main()
    {
        DateTime thisDate = new DateTime(2007, 3, 10, 0, 0, 0);
        DateTime dstDate = new DateTime(2007, 6, 10, 0, 0, 0);
        DateTimeOffset thisTime;

        thisTime = new DateTimeOffset(dstDate, new TimeSpan(-7, 0, 0));
        ShowPossibleTimeZones(thisTime);

        thisTime = new DateTimeOffset(thisDate, new TimeSpan(-6, 0, 0));
        ShowPossibleTimeZones(thisTime);

        thisTime = new DateTimeOffset(thisDate, new TimeSpan(+1, 0, 0));
        ShowPossibleTimeZones(thisTime);
    }

    private static void ShowPossibleTimeZones(DateTimeOffset offsetTime)
    {
        TimeSpan offset = offsetTime.Offset;
        ReadOnlyCollection<TimeZoneInfo> timeZones;

        Console.WriteLine($"{offsetTime.ToString()} could belong to the following time zones:");
        // Get all time zones defined on local system
        timeZones = TimeZoneInfo.GetSystemTimeZones();
        // Iterate time zones
        foreach (TimeZoneInfo timeZone in timeZones)
        {
            // Compare offset with offset for that date in that time zone
            if (timeZone.GetUtcOffset(offsetTime.DateTime).Equals(offset))
                Console.WriteLine($"   {timeZone.DisplayName}");
        }
        Console.WriteLine();
    }
}
// This example displays the following output to the console:
//       6/10/2007 12:00:00 AM -07:00 could belong to the following time zones:
//          (GMT-07:00) Arizona
//          (GMT-08:00) Pacific Time (US & Canada)
//          (GMT-08:00) Tijuana, Baja California
//
//       3/10/2007 12:00:00 AM -06:00 could belong to the following time zones:
//          (GMT-06:00) Central America
//          (GMT-06:00) Central Time (US & Canada)
//          (GMT-06:00) Guadalajara, Mexico City, Monterrey - New
//          (GMT-06:00) Guadalajara, Mexico City, Monterrey - Old
//          (GMT-06:00) Saskatchewan
//
//       3/10/2007 12:00:00 AM +01:00 could belong to the following time zones:
//          (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
//          (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
//          (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
//          (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
//          (GMT+01:00) West Central Africa
Imports System.Collections.ObjectModel

Module TimeOffsets
    Public Sub Main()
        Dim thisTime As DateTimeOffset

        thisTime = New DateTimeOffset(#06/10/2007#, New TimeSpan(-7, 0, 0))
        ShowPossibleTimeZones(thisTime)

        thisTime = New DateTimeOffset(#03/10/2007#, New TimeSpan(-6, 0, 0))
        ShowPossibleTimeZones(thisTime)

        thisTime = New DateTimeOffset(#03/10/2007#, New TimeSpan(+1, 0, 0))
        ShowPossibleTimeZones(thisTime)
    End Sub

    Private Sub ShowPossibleTimeZones(offsetTime As DateTimeOffset)
        Dim offset As TimeSpan = offsetTime.Offset
        Dim timeZones As ReadOnlyCollection(Of TimeZoneInfo)

        Console.WriteLine("{0} could belong to the following time zones:", _
                          offsetTime.ToString())
        ' Get all time zones defined on local system
        timeZones = TimeZoneInfo.GetSystemTimeZones()
        ' Iterate time zones
        For Each timeZone As TimeZoneInfo In timeZones
            ' Compare offset with offset for that date in that time zone
            If timeZone.GetUtcOffset(offsetTime.DateTime).Equals(offset) Then
                Console.WriteLine("   {0}", timeZone.DisplayName)
            End If
        Next
        Console.WriteLine()
    End Sub
End Module
' This example displays the following output to the console:
'       6/10/2007 12:00:00 AM -07:00 could belong to the following time zones:
'          (GMT-07:00) Arizona
'          (GMT-08:00) Pacific Time (US & Canada)
'          (GMT-08:00) Tijuana, Baja California
'       
'       3/10/2007 12:00:00 AM -06:00 could belong to the following time zones:
'          (GMT-06:00) Central America
'          (GMT-06:00) Central Time (US & Canada)
'          (GMT-06:00) Guadalajara, Mexico City, Monterrey - New
'          (GMT-06:00) Guadalajara, Mexico City, Monterrey - Old
'          (GMT-06:00) Saskatchewan
'       
'       3/10/2007 12:00:00 AM +01:00 could belong to the following time zones:
'          (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
'          (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
'          (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
'          (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
'          (GMT+01:00) West Central Africa

Çıktı, bu örnekteki her tarih ve saat değerinin en az üç farklı saat dilimine ait olabileceğini gösterir. 10.06.2007'nin DateTimeOffset değeri, tarih ve saat değeri yaz saatini temsil ederse, UTC'den farkının, kaynak diliminin temel UTC farkı veya görünen adında bulunan UTC farkıyla aynı olması gerekmediğini gösterir. Tek bir DateTimeOffset değeri saat dilimiyle sıkı bir şekilde bağlı olmadığından, bir saat diliminin yaz saati uygulamasına geçişini ve dönüşünü yansıtamaz. Bir DateTimeOffset değeri işlemek için tarih ve saat aritmetiği kullanıldığında bu sorun olabilir. Tarih ve saat aritmetiğinin saat diliminin ayarlama kurallarını dikkate alan bir şekilde nasıl gerçekleştirildiğinin tartışılması için bkz. Tarih ve saatlerle aritmetik işlemler gerçekleştirme.

DateTime yapısı

DateTime değeri belirli bir tarih ve saati tanımlar. Bu tarih ve saatin ait olduğu saat dilimi hakkında sınırlı bilgi sağlayan bir Kind özelliği içerir. DateTimeKind özelliği tarafından döndürülen Kind değeri, DateTime değerinin yerel saati (DateTimeKind.Local), Eşgüdümlü Evrensel Saat 'i (UTC) (DateTimeKind.Utc) veya belirtilmemiş bir saati (DateTimeKind.Unspecified) temsil edip etmediğini gösterir.

DateTime yapısı, aşağıdaki özelliklerden birine veya daha fazlasına sahip uygulamalar için uygundur:

  • Soyut tarihler ve saatlerle çalışma.
  • Saat dilimi bilgilerinin eksik olduğu tarih ve saatlerle çalışma.
  • Yalnızca UTC tarih ve saatleriyle çalışın.
  • Tarih ve saat aritmetiği gerçekleştirin, ancak bunu yaparken genel sonuçlarla ilgilenin. Örneğin, belirli bir tarih ve saate altı ay ekleyen bir ekleme işleminde, sonucun yaz saati için ayarlanıp ayarlanmadığı genellikle önemli değildir.

Belirli bir DateTime değeri UTC değerini temsil etmediği sürece, bu tarih ve saat değeri genellikle belirsizdir veya taşınabilirliği sınırlıdır. Örneğin, bir DateTime değeri yerel saati temsil ediyorsa, bu yerel saat dilimi içinde taşınabilir (yani, değer aynı saat dilimindeki başka bir sistemde seri durumdan çıkarılırsa, bu değer yine de belirli bir zaman noktasını belirsiz bir şekilde tanımlar). Yerel saat dilimi dışında, bu DateTime değeri birden çok yoruma sahip olabilir. Değerin Kind özelliği DateTimeKind.Unspecifiedise, daha da az taşınabilirdir: artık aynı saat dilimi içinde ve hatta ilk serileştirildiği sistemde bile belirsizdir. Yalnızca DateTime değeri UTC değerini temsil ederse bu değer, değerin kullanıldığı sistem veya saat diliminden bağımsız olarak zaman içinde tek bir noktayı kesin olarak tanımlar.

Önemli

DateTime verileri kaydederken veya paylaşırken UTC kullanın ve DateTime değerinin Kind özelliğini DateTimeKind.Utcolarak ayarlayın.

DateOnly yapısı

DateOnly yapısı, saat olmadan belirli bir tarihi temsil eder. Saat bileşeni olmadığından, günün başından sonuna kadar olan bir tarihi temsil eder. Bu yapı doğum tarihi, yıl dönümü tarihi, tatil veya işle ilgili tarih gibi belirli tarihleri depolamak için idealdir.

Zaman bileşenini yoksayarak DateTime kullanabilirsiniz ancak DateOnlyüzerinden DateTime kullanmanın birkaç avantajı vardır:

  • DateTime yapısı bir saat dilimi tarafından kaydırılırsa önceki veya sonraki güne geçebilir. DateOnly bir saat dilimine göre kaydırılamaz ve her zaman ayarlanan tarihi temsil eder.
  • DateTime yapısını seri hale getirme, verilerin amacını gizleyebilecek zaman bileşenini içerir. Ayrıca DateOnly daha az veriyi seri hale getirir.
  • Kod SQL Server gibi bir veritabanıyla etkileşime geçtiğinde, tüm tarihler genellikle saat içermeyen date veri türü olarak depolanır. DateOnly veritabanı türüyle daha iyi eşleşir.

DateOnlyhakkında daha fazla bilgi için bkz. DateOnly ve TimeOnly yapılarını kullanma.

Önemli

DateOnly .NET Framework için kullanılamaz.

TimeSpan yapısı

TimeSpan yapısı bir zaman aralığını temsil eder. İki tipik kullanım şekli şunlardır:

  • İki tarih ve saat değeri arasındaki zaman aralığını yansıtma. Örneğin, bir DateTime değeri başka bir değerden çıkarmak bir TimeSpan değeri döndürür.
  • Geçen süreyi ölçme. Örneğin, Stopwatch.Elapsed özelliği geçen süreyi ölçmeye başlayan TimeSpan yöntemlerinden birine çağrıldığından bu yana geçen zaman aralığını yansıtan bir Stopwatch değeri döndürür.

TimeSpan değeri, belirli bir güne başvurmadan bir saati yansıttığında DateTime değerin yerine de kullanılabilir. Bu kullanım, tarihe başvurmadan saati temsil eden bir DateTime.TimeOfDay değeri döndüren DateTimeOffset.TimeOfDay ve TimeSpan özelliklerine benzer. Örneğin, TimeSpan yapısı bir mağazanın günlük açılış veya kapanış saatini yansıtmak için veya herhangi bir normal olayın gerçekleştiği zamanı göstermek için kullanılabilir.

Aşağıdaki örnek, depo açma ve kapatma zamanları için StoreInfo nesnelerinin yanı sıra deponun saat dilimini temsil eden bir TimeSpan nesnesi içeren bir TimeZoneInfo yapısı tanımlar. Yapı ayrıca IsOpenNow ve IsOpenAtolmak üzere, yerel saat diliminde olduğu varsayılan kullanıcı tarafından belirtilen bir zamanda deponun açık olup olmadığını gösteren iki yöntem içerir.

using System;

public struct StoreInfo
{
   public String store;
   public TimeZoneInfo tz;
   public TimeSpan open;
   public TimeSpan close;

   public bool IsOpenNow()
   {
      return IsOpenAt(DateTime.Now.TimeOfDay);
   }

   public bool IsOpenAt(TimeSpan time)
   {
      TimeZoneInfo local = TimeZoneInfo.Local;
      TimeSpan offset = TimeZoneInfo.Local.BaseUtcOffset;

      // Is the store in the same time zone?
      if (tz.Equals(local)) {
         return time >= open & time <= close;
      }
      else {
         TimeSpan delta = TimeSpan.Zero;
         TimeSpan storeDelta = TimeSpan.Zero;

         // Is it daylight saving time in either time zone?
         if (local.IsDaylightSavingTime(DateTime.Now.Date + time))
            delta = local.GetAdjustmentRules()[local.GetAdjustmentRules().Length - 1].DaylightDelta;

         if (tz.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(DateTime.Now.Date + time, local, tz)))
            storeDelta = tz.GetAdjustmentRules()[tz.GetAdjustmentRules().Length - 1].DaylightDelta;

         TimeSpan comparisonTime = time + (offset - tz.BaseUtcOffset).Negate() + (delta - storeDelta).Negate();
         return comparisonTime >= open && comparisonTime <= close;
      }
   }
}
Public Structure StoreInfo
    Dim store As String
    Dim tz As TimeZoneInfo
    Dim open As TimeSpan
    Dim close As TimeSpan

    Public Function IsOpenNow() As Boolean
        Return IsOpenAt(Date.Now.TimeOfDay)
    End Function

    Public Function IsOpenAt(time As TimeSpan) As Boolean
        Dim local As TimeZoneInfo = TimeZoneInfo.Local
        Dim offset As TimeSpan = TimeZoneInfo.Local.BaseUtcOffset

        ' Is the store in the same time zone?
        If tz.Equals(local) Then
            Return time >= open AndAlso time <= close
        Else
            Dim delta As TimeSpan = TimeSpan.Zero
            Dim storeDelta As TimeSpan = TimeSpan.Zero

            ' Is it daylight saving time in either time zone?
            If local.IsDaylightSavingTime(Date.Now.Date + time) Then
                delta = local.GetAdjustmentRules(local.GetAdjustmentRules().Length - 1).DaylightDelta
            End If
            If tz.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(Date.Now.Date + time, local, tz))
                storeDelta = tz.GetAdjustmentRules(tz.GetAdjustmentRules().Length - 1).DaylightDelta
            End If
            Dim comparisonTime As TimeSpan = time + (offset - tz.BaseUtcOffset).Negate() + (delta - storeDelta).Negate
            Return (comparisonTime >= open AndAlso comparisonTime <= close)
        End If
    End Function
End Structure

StoreInfo yapısı daha sonra istemci kodu tarafından aşağıdaki gibi kullanılabilir.

public class Example
{
   public static void Main()
   {
      // Instantiate a StoreInfo object.
      var store103 = new StoreInfo();
      store103.store = "Store #103";
      store103.tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
      // Store opens at 8:00.
      store103.open = new TimeSpan(8, 0, 0);
      // Store closes at 9:30.
      store103.close = new TimeSpan(21, 30, 0);

      Console.WriteLine($"Store is open now at {DateTime.Now.TimeOfDay}: {store103.IsOpenNow()}");
      TimeSpan[] times = { new TimeSpan(8, 0, 0), new TimeSpan(21, 0, 0),
                           new TimeSpan(4, 59, 0), new TimeSpan(18, 31, 0) };
      foreach (var time in times)
         Console.WriteLine($"Store is open at {time}: {store103.IsOpenAt(time)}");
   }
}
// The example displays the following output:
//       Store is open now at 15:29:01.6129911: True
//       Store is open at 08:00:00: True
//       Store is open at 21:00:00: True
//       Store is open at 04:59:00: False
//       Store is open at 18:31:00: True
Module Example
    Public Sub Main()
        ' Instantiate a StoreInfo object.
        Dim store103 As New StoreInfo()
        store103.store = "Store #103"
        store103.tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
        ' Store opens at 8:00.
        store103.open = new TimeSpan(8, 0, 0)
        ' Store closes at 9:30.
        store103.close = new TimeSpan(21, 30, 0)

        Console.WriteLine("Store is open now at {0}: {1}",
                          Date.Now.TimeOfDay, store103.IsOpenNow())
        Dim times() As TimeSpan = {New TimeSpan(8, 0, 0),
                                    New TimeSpan(21, 0, 0),
                                    New TimeSpan(4, 59, 0),
                                    New TimeSpan(18, 31, 0)}
        For Each time In times
            Console.WriteLine("Store is open at {0}: {1}",
                              time, store103.IsOpenAt(time))
        Next
    End Sub
End Module
' The example displays the following output:
'       Store is open now at 15:29:01.6129911: True
'       Store is open at 08:00:00: True
'       Store is open at 21:00:00: False
'       Store is open at 04:59:00: False
'       Store is open at 18:31:00: False

TimeOnly yapısı

TimeOnly yapısı, günlük çalar saat veya her gün öğle yemeği yediğiniz saat gibi günün saatini temsil eder. TimeOnly, günün belirli bir saati olan 00:00:00.00000000 - 23:59:59.99999999aralığıyla sınırlıdır.

TimeOnly türü kullanılmadan önce, programcılar genellikle belirli bir saati temsil etmek için DateTime türünü veya TimeSpan türünü kullanır. Ancak, tarihsiz bir saatin benzetimini yapmak için bu yapıların kullanılması, TimeOnly çözen bazı sorunlara yol açabilir:

  • TimeSpan, kronometreyle ölçülen süre gibi geçen süreyi temsil eder. Üst aralık 29.000 yıldan fazladır ve değeri, zamanda geriye doğru hareket ettiğini göstermek için negatif olabilir. Negatif TimeSpan günün belirli bir saatini göstermez.
  • TimeSpan günün saati olarak kullanılıyorsa, 24 saatlik günün dışındaki bir değere yönlendirilebileceği riski vardır. TimeOnly bu riske sahip değil. Örneğin, bir çalışanın vardiyası 18:00'de başlıyorsa ve 8 saat sürüyorsa, TimeOnly yapısına 8 saat eklemek 2:00'ye denk gelir.
  • günün bir saati için DateTime kullanmak, rastgele bir tarihin saatle ilişkilendirilmesi ve daha sonra göz ardı edilmesi gerekir. Tarih olarak DateTime.MinValue (0001-01-01) seçmek yaygın bir uygulamadır, ancak saatler DateTime değerinden çıkarılırsa OutOfRange özel durumu oluşabilir. TimeOnly, zaman 24 saatlik zaman çerçevesi boyunca ileri ve geri hareket ederken bu sorun yaşanmamaktadır.
  • DateTime yapısını seri hale getirme, verilerin amacını gizleyebilen tarih bileşenini içerir. Ayrıca TimeOnly daha az veriyi seri hale getirir.

TimeOnlyhakkında daha fazla bilgi için bkz. DateOnly ve TimeOnly yapılarını kullanma.

Önemli

TimeOnly .NET Framework için kullanılamaz.

TimeZoneInfo sınıfı

TimeZoneInfo sınıfı, Dünyanın saat dilimlerinden herhangi birini temsil eder ve bir saat dilimindeki herhangi bir tarih ve saatin başka bir saat dilimindeki eşdeğerine dönüştürülmesi sağlar. TimeZoneInfo sınıfı tarih ve saatlerle çalışmayı mümkün kılar, böylece herhangi bir tarih ve saat değeri kesin olarak tek bir zaman noktasını tanımlar. TimeZoneInfo sınıfı da genişletilebilir. Windows sistemleri için sağlanan ve kayıt defterinde tanımlanan saat dilimi bilgilerine bağlı olsa da, özel saat dilimlerinin oluşturulmasını destekler. Ayrıca saat dilimi bilgilerinin serileştirilmesini ve tersine serileştirilmesini de destekler.

Bazı durumlarda, TimeZoneInfo sınıfından tam olarak yararlanmak için daha fazla geliştirme çalışması gerekebilir. Tarih ve saat değerleri ait oldukları saat dilimleriyle sıkı bir şekilde birleştirilmemişse, daha fazla çalışma yapılması gerekir. Uygulamanız, bir tarih ve saati ilişkili saat dilimiyle bağlamak için bir mekanizma sağlamadığı sürece, belirli bir tarih ve saat değerinin saat diliminden kopması kolaydır. Bu bilgileri bağlamanın bir yöntemi, hem tarih ve saat değerini hem de ilişkili saat dilimi nesnesini içeren bir sınıf veya yapı tanımlamaktır.

.NET'teki saat dilimi desteğinden yararlanmak için, tarih ve saat nesnesinin örneği oluşturulurken tarih ve saat değerinin ait olduğu saat dilimini bilmeniz gerekir. Saat dilimi genellikle, özellikle web veya ağ uygulamalarında bilinmez.

Ayrıca bkz.