TimeProvider nedir?
System.TimeProvider, DateTimeOffset türü olarak bir zaman noktası sağlayan bir zaman soyutlamasıdır.
TimeProvider
kullanarak kodunuzun test edilebilir ve tahmin edilebilir olmasını sağlarsınız.
TimeProvider
.NET 8'de kullanıma sunulmuştur ve .NET Framework 4.7+ ve .NET Standard 2.0'da nuGet paketi olarak da kullanılabilir.
TimeProvider sınıfı aşağıdaki özellikleri tanımlar:
- TimeProvider.GetUtcNow() ve TimeProvider.GetLocalNow()aracılığıyla tarih ve saate erişim sağlar.
- TimeProvider.GetTimestamp()ile yüksek frekanslı zaman damgaları.
- TimeProvider.GetElapsedTimeile iki zaman damgası arasındaki süreyi ölçün.
- TimeProvider.CreateTimer(TimerCallback, Object, TimeSpan, TimeSpan)ile yüksek çözünürlüklü zamanlayıcılar.
- TimeProvider.LocalTimeZoneile geçerli saat dilimini alın.
Varsayılan uygulama
.NET, TimeProvider.System özelliği aracılığıyla aşağıdaki özelliklere sahip bir TimeProvider uygulaması sağlar:
- Tarih ve saat, DateTimeOffset.UtcNow ve TimeZoneInfo.Localile hesaplanır.
- Zaman damgaları System.Diagnostics.Stopwatchtarafından sağlanır.
- Zamanlayıcılar bir iç sınıf aracılığıyla uygulanır ve System.Threading.ITimerolarak kullanıma sunulur.
Aşağıdaki örnekte, geçerli tarih ve saati almak için TimeProvider kullanımı gösterilmektedir:
Console.WriteLine($"Local: {TimeProvider.System.GetLocalNow()}");
Console.WriteLine($"Utc: {TimeProvider.System.GetUtcNow()}");
/* This example produces output similar to the following:
*
* Local: 12/5/2024 10:41:14 AM -08:00
* Utc: 12/5/2024 6:41:14 PM +00:00
*/
Console.WriteLine($"Local: {TimeProvider.System.GetLocalNow()}")
Console.WriteLine($"Utc: {TimeProvider.System.GetUtcNow()}")
' This example produces output similar to the following
'
' Local: 12/5/2024 10:41:14 AM -08:00
' Utc: 12/5/2024 6:41:14 PM +00:00
Aşağıdaki örnek, TimeProvider.GetTimestamp()ile geçen süreyi yakalamayı gösterir:
long stampStart = TimeProvider.System.GetTimestamp();
Console.WriteLine($"Starting timestamp: {stampStart}");
long stampEnd = TimeProvider.System.GetTimestamp();
Console.WriteLine($"Ending timestamp: {stampEnd}");
Console.WriteLine($"Elapsed time: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd)}");
Console.WriteLine($"Nanoseconds: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd).TotalNanoseconds}");
/* This example produces output similar to the following:
*
* Starting timestamp: 55185546133
* Ending timestamp: 55185549929
* Elapsed time: 00:00:00.0003796
* Nanoseconds: 379600
*/
Dim stampStart As Long = TimeProvider.System.GetTimestamp()
Console.WriteLine($"Starting timestamp: {stampStart}")
Dim stampEnd As Long = TimeProvider.System.GetTimestamp()
Console.WriteLine($"Ending timestamp: {stampEnd}")
Console.WriteLine($"Elapsed time: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd)}")
Console.WriteLine($"Nanoseconds: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd).TotalNanoseconds}")
' This example produces output similar to the following:
'
' Starting timestamp: 55185546133
' Ending timestamp: 55185549929
' Elapsed time: 00:00:00.0003796
' Nanoseconds: 379600
FakeTimeProvider uygulaması
Microsoft.Extensions.TimeProvider.Testing NuGet paketi, birim testi için tasarlanmış denetlenebilir bir TimeProvider
uygulaması sağlar.
Aşağıdaki listede FakeTimeProvider sınıfının bazı özellikleri açıklanmaktadır:
- Belirli bir tarih ve saat ayarlayın.
- Tarih ve saat her okunduğu zaman, tarih ve saati belirli bir miktara kadar otomatik olarak ilerletebilirsiniz.
- Tarih ve saati el ile ilerletebilirsiniz.
Özel uygulama
FakeTimeProvider zamanla öngörülebilirlik gerektiren senaryoların çoğunu kapsamalıdır, ancak yine de kendi uygulamanızı sağlayabilirsiniz. TimeProvider'dan türeyen yeni bir sınıf oluşturun ve zamanın sağlanma şeklini kontrol etmek için üyeleri geçersiz kılın. Örneğin, aşağıdaki sınıf yalnızca tek bir tarih sağlar: Ay'a iniş tarihi.
public class MoonLandingTimeProviderPST: TimeProvider
{
// July 20, 1969, at 20:17:40 UTC
private readonly DateTimeOffset _specificDateTime = new(1969, 7, 20, 20, 17, 40, TimeZoneInfo.Utc.BaseUtcOffset);
public override DateTimeOffset GetUtcNow() => _specificDateTime;
public override TimeZoneInfo LocalTimeZone => TimeZoneInfo.FindSystemTimeZoneById("PST");
}
Public Class MoonLandingTimeProviderPST
Inherits TimeProvider
'July 20, 1969, at 20:17:40 UTC
Private ReadOnly _specificDateTime As New DateTimeOffset(1969, 7, 20, 20, 17, 40, TimeZoneInfo.Utc.BaseUtcOffset)
Public Overrides Function GetUtcNow() As DateTimeOffset
Return _specificDateTime
End Function
Public Overrides ReadOnly Property LocalTimeZone As TimeZoneInfo
Get
Return TimeZoneInfo.FindSystemTimeZoneById("PST")
End Get
End Property
End Class
Bu sınıfı kullanan kod MoonLandingTimeProviderPST.GetUtcNow
çağırırsa UTC cinsinden ayın giriş tarihi döndürülür.
MoonLandingTimeProviderPST.GetLocalNow
çağrılırsa, temel sınıf MoonLandingTimeProviderPST.LocalTimeZone
GetUtcNow
üzerinde uygular ve PST zaman dilimindeki ay inişi tarihini ve saatini döndürür.
Zamanı denetlemenin yararlılığını göstermek için aşağıdaki örneği göz önünde bulundurun. Uygulama her gün ilk kez açıldığında kullanıcıya selam gönderen bir takvim uygulaması yazdığınızı varsayalım. Uygulama, geçerli günün kendisiyle ilişkilendirilmiş bir etkinliği olduğunda (örneğin, ay girişinin yıldönümü) özel bir selamlama söyler.
public static class CalendarHelper
{
static readonly DateTimeOffset MoonLandingDateTime = new(1969, 7, 20, 20, 17, 40, TimeZoneInfo.Utc.BaseUtcOffset);
public static void SendGreeting(TimeProvider currentTime, string name)
{
DateTimeOffset localTime = currentTime.GetLocalNow();
Console.WriteLine($"Good morning, {name}!");
Console.WriteLine($"The date is {localTime.Date:d} and the day is {localTime.Date.DayOfWeek}.");
if (localTime.Date.Month == MoonLandingDateTime.Date.Month
&& localTime.Date.Day == MoonLandingDateTime.Date.Day)
{
Console.WriteLine("Did you know that on this day in 1969 humans landed on the Moon?");
}
Console.WriteLine($"I hope you enjoy your day!");
}
}
Public Module CalendarHelper
ReadOnly MoonLandingDateTime As DateTimeOffset = #7/20/1969 20:17:40#
Public Sub SendGreeting(currentTime As TimeProvider, name As String)
Dim localTime As DateTimeOffset = currentTime.GetLocalNow()
Console.WriteLine($"Good morning, {name}!")
Console.WriteLine($"The date is {localTime.Date:d} and the day is {localTime.Date.DayOfWeek}.")
If (localTime.Date.Month = MoonLandingDateTime.Date.Month _
And localTime.Date.Day = MoonLandingDateTime.Date.Day) Then
Console.WriteLine("Did you know that on this day in 1969 humans landed on the Moon?")
End If
Console.WriteLine($"I hope you enjoy your day!")
End Sub
End Module
TimeProvideryerine geçerli tarih ve saati almak için önceki kodu DateTime veya DateTimeOffset ile yazma eğiliminde olabilirsiniz. Ancak birim testi yaparken DateTime veya DateTimeOffset üzerinde çalışmak zordur. Testleri ayın giriş günü ve ayında çalıştırmanız veya kodu daha küçük ama test edilebilir birimler halinde soyutlamanız gerekir.
Uygulamanızın normal işlemi geçerli tarih ve saati almak için TimeProvider.System
kullanır:
CalendarHelper.SendGreeting(TimeProvider.System, "Eric Solomon");
/* This example produces output similar to the following:
*
* Good morning, Eric Solomon!
* The date is 12/5/2024 and the day is Thursday.
* I hope you enjoy your day!
*/
CalendarHelper.SendGreeting(TimeProvider.System, "Eric Solomon")
' This example produces output similar to the following:
'
' Good morning, Eric Solomon!
' The date is 12/5/2024 and the day is Thursday.
' I hope you enjoy your day!
Ayrıca birim testleri, ay girişinin yıldönümünü test etme gibi belirli senaryoları test etmek için yazılabilir:
CalendarHelper.SendGreeting(new MoonLandingTimeProviderPST(), "Eric Solomon");
/* This example produces output similar to the following:
*
* Good morning, Eric Solomon!
* The date is 7/20/1969 and the day is Sunday.
* Did you know that on this day in 1969 humans landed on the Moon?
* I hope you enjoy your day!
*/
CalendarHelper.SendGreeting(New MoonLandingTimeProviderPST(), "Eric Solomon")
' This example produces output similar to the following:
'
' Good morning, Eric Solomon!
' The date is 7/20/1969 and the day is Sunday.
' Did you know that on this day in 1969 humans landed on the Moon?
' I hope you enjoy your day!
.NET ile kullanma
.NET 8'den başlayarak, TimeProvider sınıfı çalışma zamanı kitaplığı tarafından sağlanır. .NET'in veya .NET Standard 2.0'ı hedefleyen kitaplıkların eski sürümleri, Microsoft.Bcl.TimeProvider NuGet paketinebaşvurmalıdır.
Zaman uyumsuz programlamayla ilgili aşağıdaki yöntemler TimeProvider
ile çalışır:
- CancellationTokenSource(TimeSpan, TimeProvider)
- Task.Delay(TimeSpan, TimeProvider)
- Task.Delay(TimeSpan, TimeProvider, CancellationToken)
- Task.WaitAsync(TimeSpan, TimeProvider)
- Task.WaitAsync(TimeSpan, TimeProvider, CancellationToken)
.NET Framework ile kullanma
TimeProvider, Microsoft.Bcl.TimeProvider NuGet paketitarafından uygulanır.
Zaman uyumsuz programlama senaryolarında TimeProvider
ile çalışma desteği aşağıdaki uzantı yöntemleriyle eklendi:
- TimeProviderTaskExtensions.CreateCancellationTokenSource(TimeProvider, TimeSpan)
- TimeProviderTaskExtensions.Delay(TimeProvider, TimeSpan, CancellationToken)
- TimeProviderTaskExtensions.WaitAsync(Task, TimeSpan, TimeProvider, CancellationToken)
- TimeProviderTaskExtensions.WaitAsync<TResult>(Task<TResult>, TimeSpan, TimeProvider, CancellationToken)