108 votes

C # DateTime.Now precision

Je viens de croiser un comportement inattendu avec DateTime.UtcNow tout en faisant quelques tests unitaires. Il semble que lorsque vous appelez DateTime.Maintenant/UtcNow en succession rapide, il semble pour vous redonner la même valeur pour un plus long que prévu intervalle de temps, plutôt que de capturer plus précis à la milliseconde à la fois.

Je sais qu'il est un Chronomètre de classe qui seraient mieux adaptés pour faire des précise les mesures de temps, mais j'étais curieux de savoir si quelqu'un pourrait expliquer ce comportement dans DateTime? Est-il un fonctionnaire de précision documenté pour le type DateTime.Maintenant (par exemple, précise à l'intérieur de 50ms?)? Pourquoi DateTime.Maintenant, être moins précis que ce que la plupart des CPU horloges pourrait-il gérer? Peut-être que c'est juste conçu pour le plus petit dénominateur commun de l'UC?

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();
}

210voto

Eric Lippert Points 300275

Pourquoi DateTime.Maintenant, être moins précis que ce que la plupart des CPU horloges pourrait-il gérer?

Une bonne horloge doit être à la fois précis et exacts; ceux qui sont différents. Comme la vieille blague, une pendule arrêtée est tout à fait exacte deux fois par jour, une horloge, une minute lente n'est jamais précis à tout moment. Mais l'horloge d'une minute lente est toujours précis à la minute la plus proche, tandis que l'arrêt de l'horloge n'a pas de précision utile à tous.

Pourquoi le DateTime être précis , disons une microseconde, quand il ne peut pas être précis à la microseconde? La plupart des gens n'ont pas une source officielle au temps des signaux qui sont précis à la microseconde. Par conséquent, un préavis de six chiffres après la virgule de précision, le dernier dont cinq sont des ordures serait mentir.

Rappelez-vous, le but de la question est de représenter une date et une heure. Haute précision timings n'est pas du tout le but de DateTime; comme vous le notez, c'est le but de Chronomètre. Le but de DateTime est de représenter une date et une heure pour l'utilisation de l'affichage de l'heure actuelle pour l'utilisateur, le calcul du nombre de jours jusqu'à mardi prochain, et ainsi de suite.

En bref, "quelle heure est-il?" et "combien de temps cela prendrait-il?" sont des questions totalement différentes; n'utilisez pas un outil conçu pour répondre à une question à la réponse de l'autre.

Merci pour la question; cela fera un bon article de blog! :-)

19voto

Reed Copsey Points 315315

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 se situe généralement autour de 15 ou 16 ms. (Sur mon système, il s’agit de 14 ms environ de mes tests, mais j’ai vu des ordinateurs portables dont la précision est plus proche de 35 à 40 ms.)

Peter Bromberg a écrit un article sur le minutage de code de haute précision en C #, qui traite de cela.

12voto

Jimmy Points 1197

Je voudrais un Datetime.Now :) précis, alors je l'ai concocté:

 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); } }
}
 

7voto

Scott Anderson Points 7522

Pour ce que cela vaut, à moins de vérifier réellement la source .NET, Eric Lippert a commenté cette question SO de sorte que DateTime n’a une précision d’environ que 30 ms. Le raisonnement pour ne pas être précis à la nanoseconde, selon ses mots, est qu'il "n'a pas besoin de l'être".

3voto

Tomas Vana Points 5686

De la documentation MSDN :

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X