C # DateTime.Now precisión

Me encontré con un comportamiento inesperado con DateTime.UtcNow mientras hacía algunas pruebas unitarias. Parece que cuando llama a DateTime.Now/UtcNow en sucesión rápida, parece devolverle el mismo valor por un intervalo de tiempo mayor 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 pudiera explicar este comportamiento en DateTime. ¿Existe una precisión oficial documentada para DateTime.Now (por ejemplo, precisa dentro de 50 ms?)? ¿Por qué DateTime.Now se haría menos preciso que lo que la mayoría de los relojes de CPU podrían manejar? ¿Tal vez está diseñado para la CPU con el mínimo común denominador?

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

¿Por qué DateTime.Now se haría menos preciso que lo que la mayoría de los relojes de CPU podrían manejar?

Un buen reloj debería ser preciso y preciso ; esos son diferentes Como dice la vieja broma, un reloj parado es exactamente exacto dos veces al día, un reloj de 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 parado no tiene precisión útil en absoluto.

¿Por qué el DateTime debe ser preciso , por ejemplo, un microsegundo cuando posiblemente no sea exacto al microsegundo? La mayoría de las personas no tienen ninguna fuente de señales horarias oficiales que sean precisas a un microsegundo. Por lo tanto, dar seis dígitos después del lugar decimal de precisión , los últimos cinco de los cuales son basura estaría mintiendo .

Recuerde, el objective de DateTime es representar una fecha y hora . Los tiempos de alta precisión no son el propósito de DateTime; como notas, ese es el propósito de StopWatch. El objective de DateTime es representar una fecha y una hora para fines 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 use una herramienta diseñada para responder una pregunta para responder la otra.

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

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 está a unos 14 ms de mi prueba, pero he visto algunas laptops donde está más cerca de la precisión de 35-40 ms.)

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

Me gustaría un Datetime.Now preciso :), así que preparé 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); } } } 

Por lo que vale, a menos que realmente compruebe el origen .NET, Eric Lippert hizo un comentario sobre esta pregunta SO diciendo que DateTime solo tiene una precisión de aproximadamente 30 ms. El razonamiento para no ser exacto en nanosegundos, en sus palabras, es que “no tiene que ser así”.

Desde MSDN , verá 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 usando QueryPerformanceCounter .

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 posterior es de 10 ms 🙂