C # 日期时间,现在精确

我在日期时间上遇到了一些意想不到的情况。在进行一些单元测试时使用 UtcNow。当您调用 DateTime 时,似乎。Now/UtcNow 在快速连续的情况下,似乎在比预期更长的时间间隔内返回相同的值,而不是捕获更精确的毫秒增量。

我知道有一个秒表类更适合做精确的时间测量,但我很好奇,如果有人可以解释这种行为在日期时间?是否有关于日期时间的官方精度文档。现在(例如,精确到50毫秒以内?)?为什么日期时间。现在比大多数 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();
}
60894 次浏览

For what it's worth, short of actually checking the .NET source, Eric Lippert provided a comment on this SO question saying that DateTime is only accurate to approx 30 ms. The reasoning for not being nanosecond accurate, in his words, is that it "doesn't need to be."

From MSDN documentation:

The resolution of this property depends on the system timer.

They also claim that the approximate resolution on Windows NT 3.5 and later is 10 ms :)

DateTime's precision is somewhat specific to the system it's being run on. The precision is related to the speed of a context switch, which tends to be around 15 or 16 ms. (On my system, it is actually about 14 ms from my testing, but I've seen some laptops where it's closer to 35-40 ms accuracy.)

Peter Bromberg wrote an article on high precision code timing in C#, which discusses this.

From MSDN you'll find that DateTime.Now has an approximate resolution of 10 milliseconds on all NT operating systems.

The actual precision is hardware dependent. Better precision can be obtained using QueryPerformanceCounter.

Why would DateTime.Now be made less precise than what most CPU clocks could handle?

A good clock should be both precise and accurate; those are different. As the old joke goes, a stopped clock is exactly accurate twice a day, a clock a minute slow is never accurate at any time. But the clock a minute slow is always precise to the nearest minute, whereas a stopped clock has no useful precision at all.

Why should the DateTime be precise to, say a microsecond when it cannot possibly be accurate to the microsecond? Most people do not have any source for official time signals that are accurate to the microsecond. Therefore giving six digits after the decimal place of precision, the last five of which are garbage would be lying.

Remember, the purpose of DateTime is to represent a date and time. High-precision timings is not at all the purpose of DateTime; as you note, that's the purpose of StopWatch. The purpose of DateTime is to represent a date and time for purposes like displaying the current time to the user, computing the number of days until next Tuesday, and so on.

In short, "what time is it?" and "how long did that take?" are completely different questions; don't use a tool designed to answer one question to answer the other.

Thanks for the question; this will make a good blog article! :-)

I would like a precise Datetime.Now :), so I cooked this up:

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

The resolution of this property depends on the system timer, which depends on the underlying operating system. It tends to be between 0.5 and 15 milliseconds.

As a result, repeated calls to the Now property in a short time interval, such as in a loop, may return the same value.

MSDN Link