Pregunta

Me encontré en algún comportamiento inesperado con fecha y hora.UtcNow mientras que haciendo algunas pruebas de unidad.Parece que cuando llame DateTime.Ahora/UtcNow en rápida sucesión, parece darle de nuevo el mismo valor para un más largo de lo esperado, el intervalo de tiempo, en lugar de la captura más precisa incrementos de un milisegundo.

Sé que hay una clase Stopwatch que sería más adecuado para hacer precisas mediciones de tiempo, pero tenía curiosidad si alguien podría explicar este comportamiento en DateTime?Hay un oficial de precisión documentado para DateTime.Ahora (por ejemplo, precisa que dentro de 50 ms?)?¿Por qué DateTime.Ahora ser menos precisa de lo que la mayoría de los relojes de la CPU puede manejar?Tal vez es sólo diseñado para el mínimo común denominador 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();
}
¿Fue útil?

Solución

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

Un buen reloj debe ser precisa y precisa;aquellos que son diferentes.Como el viejo chiste va, detenido el reloj es exactamente correcta dos veces al día, un reloj, un minuto lento nunca es exacta en cualquier momento.Pero el reloj de un minuto lento siempre es precisa al minuto más cercano, mientras que un detenido reloj no tiene ninguna utilidad precisión en todo.

¿Por qué la DateTime ser precisa a decir de un microsegundo, cuando no puede ser, posiblemente, precisa para el microsegundo?La mayoría de la gente no tiene ninguna fuente oficial de señales de tiempo que se precisa para el microsegundo.Por lo tanto, dar seis dígitos después del decimal de precisión, el pasado cinco de los cuales son la basura sería la mentira.

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

En definitiva, "¿qué hora es?" y "żcuánto tiempo tuvo que tomar?" son completamente diferentes preguntas;no use una herramienta diseñada para responder a una pregunta que responder a la otra.

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

Otros consejos

precisión de DateTime es algo específico del sistema que está siendo ejecutado en. La precisión está relacionada con la velocidad de un cambio de contexto, que tiende a ser alrededor de 15 o 16 ms. (En mi sistema, es realmente acerca de 14 ms de mi prueba, pero he visto algunos ordenadores portátiles en las que es más cerca de 35-40 ms exactitud.)

un artículo sobre la alta precisión sincronismo de código en C #, donde se discute este .

Me gustaría un Datetime.Now precisa :), por lo 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); } }
}

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

La precisión real es dependiente del hardware. Mejor precisión se puede obtener utilizando QueryPerformanceCounter .

Por lo que vale, en realidad por debajo de control de la fuente .NET, Eric Lippert proporciona un comentario en esta pregunta SO diciendo que DateTime es sólo exacta a unos 30 ms. El razonamiento para no ser exacta nanosegundo, en sus palabras, es que "no tiene que ser."

De MSDN la documentación :

  

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 versiones posteriores es de 10 ms):

  

La resolución de esta propiedad depende del temporizador del sistema, el cual   depende del sistema operativo subyacente. Tiende a ser entre 0,5   y 15 milisegundos.

Como resultado, llamadas repetidas a la propiedad Ahora en un intervalo de tiempo corto, como en un bucle, pueden devolver el mismo valor.

MSDN Enlace

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top