Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
System.TimeProvider is een abstractie van tijd die een moment in de tijd als DateTimeOffset type biedt. Door te gebruiken TimeProvider, zorgt u ervoor dat uw code testbaar en voorspelbaar is.
TimeProvider is beschikbaar voor de volgende frameworks:
| Raamwerk | Opmerkingen |
|---|---|
| .NET 8+ | Opgenomen in het framework. |
| .NET 5 - .NET 7 | Geleverd in het Microsoft.Bcl.TimeProvider NuGet-pakket. |
| .NET Framework 4.6.2+ | Geleverd in het Microsoft.Bcl.TimeProvider NuGet-pakket. |
| .NET Standard 2.0 | Geleverd in het Microsoft.Bcl.TimeProvider NuGet-pakket. |
De TimeProvider klasse definieert de volgende mogelijkheden:
- Biedt toegang tot de datum en tijd via TimeProvider.GetUtcNow() en TimeProvider.GetLocalNow().
- Tijdstempels met hoge frequentie met TimeProvider.GetTimestamp().
- Meet de tijd tussen twee tijdstempels met TimeProvider.GetElapsedTime.
- Timers met hoge resolutie, inclusief TimeProvider.CreateTimer(TimerCallback, Object, TimeSpan, TimeSpan).
- Haal de huidige tijdzone op met TimeProvider.LocalTimeZone.
Standaard implementatie
.NET biedt een implementatie van TimeProvider via de TimeProvider.System eigenschap, met de volgende kenmerken:
- Datum en tijd worden berekend met behulp van DateTimeOffset.UtcNow en TimeZoneInfo.Local.
- Tijdstempels worden geleverd door System.Diagnostics.Stopwatch.
- Timers worden geïmplementeerd via een interne klasse en weergegeven als System.Threading.ITimer.
In het volgende voorbeeld ziet u hoe u met TimeProvider de huidige datum en tijd kunt ophalen:
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
In het volgende voorbeeld ziet u hoe u verstreken tijd kunt vastleggen met behulp van TimeProvider.GetTimestamp():
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-implementatie
Het NuGet-pakket Microsoft.Extensions.TimeProvider.Testing biedt een controleerbare TimeProvider implementatie die is ontworpen voor eenheidstests.
In de volgende lijst worden enkele van de mogelijkheden van de FakeTimeProvider klasse beschreven:
- Stel een specifieke datum en tijd in.
- De datum en tijd automatisch vooruitgaan met een opgegeven hoeveelheid wanneer de datum en tijd worden gelezen.
- De datum en tijd handmatig vooruit instellen.
Aangepaste implementatie
Hoewel FakeTimeProvider de meeste scenario's behandelt waarvoor voorspelbaarheid met tijd is vereist, kunt u nog steeds uw eigen implementatie bieden. Maak een nieuwe klasse die is afgeleid van TimeProvider en overschrijf leden om te controleren hoe tijd wordt verstrekt. De volgende klasse biedt bijvoorbeeld slechts één datum, de datum van de maanlanding:
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
Als de code gebruikmaakt van deze klasse MoonLandingTimeProviderPST.GetUtcNow, wordt de datum van de maanlanding in UTC geretourneerd. Als MoonLandingTimeProviderPST.GetLocalNow wordt aangeroepen, past de basisklasse MoonLandingTimeProviderPST.LocalTimeZone toe op GetUtcNow en retourneert het de maanlandingsdatum en -tijd in de PST-tijdzone.
Bekijk het volgende voorbeeld om de bruikbaarheid van de controletijd te demonstreren. Stel dat u een agenda-app schrijft die een begroeting naar de gebruiker verzendt wanneer de app elke dag voor het eerst wordt geopend. De app zegt een speciale begroeting wanneer er een gebeurtenis aan de huidige dag is gekoppeld, zoals het jubileum van de maanlanding.
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
Mogelijk bent u geneigd om de vorige code te schrijven met DateTime of DateTimeOffset om de huidige datum en tijd op te halen, in plaats van TimeProvider. Met unittesting is het echter moeilijk om direct om DateTime of DateTimeOffset heen te werken. U moet de tests uitvoeren op de dag en maand van de maanlanding of de code verder abstraheren in kleinere maar testbare eenheden.
De normale werking van uw app gebruikt TimeProvider.System om de huidige datum en tijd op te halen:
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!
En eenheidstests kunnen worden geschreven om specifieke scenario's te testen, zoals het testen van het jubileum van de maanlanding:
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!
Gebruiken met .NET
Vanaf .NET 8 biedt de runtimebibliotheek de TimeProvider klasse. Oudere versies van .NET of bibliotheken die gericht zijn op .NET Standard 2.0, moeten verwijzen naar het Microsoft.Bcl.TimeProvider NuGet-pakket.
De volgende methoden met betrekking tot asynchrone programmering werken met TimeProvider:
- CancellationTokenSource(TimeSpan, TimeProvider)
- Task.Delay(TimeSpan, TimeProvider)
- Task.Delay(TimeSpan, TimeProvider, CancellationToken)
- Task.WaitAsync(TimeSpan, TimeProvider)
- Task.WaitAsync(TimeSpan, TimeProvider, CancellationToken)
Gebruiken met .NET Framework
Het Microsoft.Bcl.TimeProvider NuGet-pakket implementeert TimeProvider.
Ondersteuning voor het werken met TimeProvider in asynchrone programmeerscenario's is toegevoegd via de volgende uitbreidingsmethoden:
- TimeProviderTaskExtensions.CreateCancellationTokenSource(TimeProvider, TimeSpan)
- TimeProviderTaskExtensions.Delay(TimeProvider, TimeSpan, CancellationToken)
- TimeProviderTaskExtensions.WaitAsync(Task, TimeSpan, TimeProvider, CancellationToken)
- TimeProviderTaskExtensions.WaitAsync<TResult>(Task<TResult>, TimeSpan, TimeProvider, CancellationToken)