C # DateTime.Now précision

Je viens de rencontrer un comportement inattendu avec DateTime.UtcNow lors de certains tests unitaires. Il semble que lorsque vous appelez DateTime.Now/UtcNow dans une succession rapide, il semble vous redonner la même valeur pour un intervalle de temps plus long que prévu, plutôt que de saisir des incréments de millisecondes plus précis.

Je sais qu’il existe une classe Chronomètre qui conviendrait mieux pour effectuer des mesures de temps précises, mais j’étais curieux de savoir si quelqu’un pouvait expliquer ce comportement dans DateTime? Existe-t-il une précision officielle documentée pour DateTime.Now (par exemple, précise à moins de 50 ms?)? Pourquoi DateTime serait-il désormais moins précis que ce que la plupart des horloges de processeur pourraient gérer? Peut-être que c’est juste conçu pour le plus petit dénominateur commun CPU?

public static void Main(ssortingng[] 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(); } 

Pourquoi DateTime serait-il désormais moins précis que ce que la plupart des horloges de processeur pourraient gérer?

Une bonne horloge doit être à la fois précise et précise ; ceux-ci sont différents. Comme le dit la vieille blague, une horloge arrêtée est exactement exacte deux fois par jour, une heure par minute lente n’est jamais exacte à aucun moment. Mais l’horloge d’une minute lente est toujours précise à la minute près, alors qu’une horloge arrêtée n’a aucune précision utile.

Pourquoi le DateTime devrait-il être précis , disons une microseconde alors qu’il ne peut pas être exact à la microseconde? La plupart des gens ne disposent d’aucune source pour des signaux horaires officiels précis à la microseconde. Donc, donner six chiffres après la décimale de précision , les cinq derniers étant des ordures serait couché .

Rappelez-vous que l’object de DateTime est de représenter une date et une heure . Les minutages de haute précision ne sont pas du tout utiles à DateTime; comme vous le notez, c’est le but de StopWatch. Le but de DateTime est de représenter une date et une heure à des fins telles que l’affichage de l’heure actuelle à l’utilisateur, le calcul du nombre de jours jusqu’au mardi suivant, etc.

En bref, “quelle heure est-il?” et “combien de temps cela a-t-il pris?” sont des questions complètement différentes; n’utilisez pas un outil conçu pour répondre à une question pour répondre à l’autre.

Merci pour la question cela fera un bon article de blog! 🙂

La précision de DateTime est quelque peu spécifique au système sur lequel il est exécuté. La précision est liée à la vitesse d’un changement de contexte, qui a tendance à être d’environ 15 ou 16 ms. (Sur mon système, il s’agit en fait de 14 ms environ de mes tests, mais j’ai vu des ordinateurs portables dont la précision est proche de 35-40 ms.)

Peter Bromberg a écrit un article sur la synchronisation du code de haute précision en C #, qui en discute.

Je voudrais un datetime.Now précis :), alors j’ai préparé ceci:

 public class PreciseDatetime { // using DateTime.Now resulted in many many log events with the same timestamp. // use static variables in case there are many instances of this class in use in the same program // (that way they will all be in sync) private static readonly Stopwatch myStopwatch = new Stopwatch(); private static System.DateTime myStopwatchStartTime; static PreciseDatetime() { Reset(); try { // In case the system clock gets updated SystemEvents.TimeChanged += SystemEvents_TimeChanged; } catch (Exception) { } } static void SystemEvents_TimeChanged(object sender, EventArgs e) { Reset(); } // SystemEvents.TimeChanged can be slow to fire (3 secs), so allow forcing of reset static public void Reset() { myStopwatchStartTime = System.DateTime.Now; myStopwatch.Restart(); } public System.DateTime Now { get { return myStopwatchStartTime.Add(myStopwatch.Elapsed); } } } 

Pour ce que cela vaut, à moins de vérifier la source .NET, Eric Lippert a fourni un commentaire sur cette question SO indiquant que DateTime n’est précis qu’à environ 30 ms. Le raisonnement pour ne pas être précis à la nanoseconde, selon ses mots, est que cela “n’a pas besoin d’être”.

De MSDN, vous trouverez que DateTime.Now a une résolution approximative de 10 millisecondes sur tous les systèmes d’exploitation NT.

La précision réelle dépend du matériel. Une meilleure précision peut être obtenue en utilisant QueryPerformanceCounter .

De la documentation MSDN :

La résolution de cette propriété dépend du temporisateur du système.

Ils affirment également que la résolution approximative sur Windows NT 3.5 et versions ultérieures est de 10 ms 🙂