Aracılığıyla paylaş


TimeProvider nedir?

System.TimeProvider, DateTimeOffset türü olarak bir zaman noktası sağlayan bir zaman soyutlamasıdır. TimeProviderkullanarak 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:

Varsayılan uygulama

.NET, TimeProvider.System özelliği aracılığıyla aşağıdaki özelliklere sahip bir TimeProvider uygulaması sağlar:

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.LocalTimeZoneGetUtcNow ü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 TimeProviderile çalışır:

.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: