Właśnie napotkałem nieoczekiwane zachowanie z DateTime.UtcNow podczas wykonywania niektórych testów jednostkowych. Wydaje się, że gdy wywołujesz DateTime.Now/UtcNow w krótkich odstępach czasu, wydaje się, że zwraca tę samą wartość przez dłuższy niż oczekiwany przedział czasu, zamiast przechwytywać dokładniejsze przyrosty milisekund.
Wiem, że istnieje klasa Stopwatch, która lepiej nadawałaby się do wykonywania precyzyjnych pomiarów czasu, ale byłem ciekaw, czy ktoś mógłby wyjaśnić to zachowanie w DateTime? Czy istnieje udokumentowana oficjalna dokładność dla DateTime.Now (na przykład z dokładnością do 50 ms?)? Dlaczego DateTime.Now miałoby być mniej precyzyjne niż te, z którymi radzi sobie większość zegarów procesora? Może jest po prostu zaprojektowany dla procesora z najniższym wspólnym mianownikiem?
public static void Main(string[] args)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i=0; i<1000; i++)
{
var now = DateTime.Now;
Console.WriteLine(string.Format(
"Ticks: {0}\tMilliseconds: {1}", now.Ticks, now.Millisecond));
}
stopwatch.Stop();
Console.WriteLine("Stopwatch.ElapsedMilliseconds: {0}",
stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
Odpowiedzi:
Dobry zegar powinien być zarówno precyzyjny, jak i dokładny ; te są różne. Jak głosi stary żart, zatrzymany zegar jest dokładny dwa razy dziennie, a zegar spowolniony o minutę nigdy nie jest dokładny w żadnym momencie. Ale zegar spowolniony o minutę jest zawsze dokładny do najbliższej minuty, podczas gdy zatrzymany zegar nie ma żadnej użytecznej precyzji.
Dlaczego DateTime miałby być dokładny do, powiedzmy mikrosekundy, skoro nie może być dokładny do mikrosekundy? Większość ludzi nie ma żadnego źródła oficjalnych sygnałów czasu z dokładnością do mikrosekundy. Dlatego podanie sześciu cyfr po przecinku dokładności , z których pięć ostatnich to śmieci, byłoby kłamstwem .
Pamiętaj, że celem DateTime jest reprezentowanie daty i godziny . Wysoka precyzja chronometrażu nie jest w ogóle celem DateTime; jak zauważyłeś, taki jest cel StopWatch. Celem DateTime jest przedstawienie daty i godziny do celów takich jak wyświetlanie aktualnego czasu użytkownikowi, obliczanie liczby dni do następnego wtorku i tak dalej.
Krótko mówiąc, „która jest godzina?” i „jak długo to trwało?” to zupełnie inne pytania; nie używaj narzędzia przeznaczonego do udzielania odpowiedzi na jedno pytanie, aby odpowiedzieć na drugie.
Dzięki za pytanie; to będzie dobry artykuł na blogu! :-)
źródło
Precyzja DateTime jest nieco specyficzna dla systemu, w którym jest uruchamiany. Precyzja jest związana z szybkością przełączania kontekstu, która zwykle wynosi około 15 lub 16 ms. (W moim systemie jest to faktycznie około 14 ms od mojego testu, ale widziałem niektóre laptopy, w których jest bliżej 35-40 ms dokładności.)
Peter Bromberg napisał artykuł o taktowaniu kodu w języku C # o wysokiej precyzji , w którym omówiono to.
źródło
Chciałbym mieć dokładną datę i godzinę. Teraz :), więc ułożyłem to:
źródło
Z MSDN dowiesz się, że
DateTime.Now
ma przybliżoną rozdzielczość 10 milisekund we wszystkich systemach operacyjnych NT.Rzeczywista precyzja zależy od sprzętu. Lepszą precyzję można uzyskać za pomocą
QueryPerformanceCounter
.źródło
Jeśli chodzi o to, co jest warte, poza faktycznym sprawdzeniem źródła .NET, Eric Lippert skomentował to pytanie SO, mówiąc, że DateTime jest dokładny tylko do około 30 ms. Jego zdaniem, powodem, dla którego nie jest on dokładny w nanosekundach, jest to, że „nie musi być”.
źródło
Z dokumentacji MSDN :
Twierdzą też, że przybliżona rozdzielczość w systemie Windows NT 3.5 i nowszych to 10 ms :)
źródło
W rezultacie powtarzające się wywołania właściwości Now w krótkim przedziale czasu, na przykład w pętli, mogą zwrócić tę samą wartość.
MSDN Link
źródło