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
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
yöntemini veya yöntemini çağırarak ConvertTimeToUtc bir saati Eşgüdümlü Evrensel Saat'e (UTC) dönüştürün ConvertTime .
Aritmetik işlemi UTC saatinde gerçekleştirin.
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.