C # DateTime.Ahora precisión


Me encontré con un comportamiento inesperado con DateTime.UtcNow mientras hace algunas pruebas unitarias. Parece que cuando se llama DateTime.Ahora / UtcNow en rápida sucesión, parece devolverle el mismo valor por un intervalo de tiempo más largo de lo esperado, en lugar de capturar incrementos de milisegundos más precisos.

Sé que hay una clase de cronómetro que sería más adecuada para hacer mediciones de tiempo precisas, pero tenía curiosidad si alguien podría explicar este comportamiento en DateTime? ¿Hay una precisión oficial documentada para DateTime?Ahora(por ejemplo, precisa dentro de 50 ms?)? Por qué DateTime.Ahora ser menos preciso de lo que la mayoría de los relojes de la CPU podría manejar? Tal vez sólo está diseñado para el menor denominador común de la CPU?

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();
}
Author: Peter Mortensen, 2010-01-27

6 answers

Por qué DateTime.Ahora ser menos preciso de lo que la mayoría de los relojes de la CPU podría manejar?

Un buen reloj debe ser preciso y preciso; esos son diferentes. Como dice la vieja broma, un reloj detenido es exactamente preciso dos veces al día, un reloj un minuto lento nunca es preciso en ningún momento. Pero el reloj un minuto lento siempre es preciso al minuto más cercano, mientras que un reloj detenido no tiene precisión útil en absoluto.

¿por Qué la DateTime ser precisopara, digamos un microsegundo cuando no puede ser preciso para el microsegundo? La mayoría de las personas no tienen ninguna fuente de señales horarias oficiales que sean precisas al microsegundo. Por lo tanto, dar seis dígitos después del lugar decimal de precisión, los últimos cinco de los cuales son basura sería mentira.

Recuerde, el propósito de DateTime es representar una fecha y hora. Tiempos de alta precisión no es en absoluto el propósito de DateTime; como se nota, ese es el propósito de Cronómetro. El propósito de DateTime es representar una fecha y hora para propósitos como mostrar la hora actual al usuario, calcular el número de días hasta el próximo martes, y así sucesivamente.

En resumen, "¿qué hora es?"y" ¿cuánto tiempo tomó eso?"son preguntas completamente diferentes; no utilice una herramienta diseñada para responder a una pregunta para responder a la otra.

Gracias por la pregunta; esto hará un buen artículo de blog! :-)

 160
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-27 00:36:30

La precisión de DateTime es algo específica para el sistema en el que se está ejecutando. La precisión está relacionada con la velocidad de un cambio de contexto, que tiende a ser de alrededor de 15 o 16 ms. (En mi sistema, en realidad es de aproximadamente 14 ms de mi prueba, pero he visto algunas computadoras portátiles donde está más cerca de 35-40 ms de precisión.)

Peter Bromberg escribió un artículo sobre sincronización de código de alta precisión en C#, que discute esto.

 16
Author: Reed Copsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-03 15:15:31

Me gustaría una precisa Datetime.Ahora:), así que cociné esto:

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); } }
}
 12
Author: Jimmy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-04 19:19:16

Por lo que vale la pena, a excepción de comprobar realmente la fuente. NET, Eric Lippert proporcionó un comentario sobre esta pregunta SO diciendo que DateTime solo es precisa aproximadamente 30 ms.El razonamiento para no ser precisa en nanosegundos, en sus palabras, es que "no tiene que ser."

 5
Author: Scott Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:40

Desde MSDN encontrará que DateTime.Now tiene una resolución aproximada de 10 milisegundos en todos los sistemas operativos NT.

La precisión real depende del hardware. Se puede obtener una mejor precisión utilizando QueryPerformanceCounter.

 4
Author: Kevin Montrose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-26 22:28:50

De la documentación de MSDN :

La resolución de esta propiedad depende del temporizador del sistema.

También afirman que la resolución aproximada en Windows NT 3.5 y posteriores es de 10 ms:)

 3
Author: Tomas Vana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-03 15:14:32