提问人:Andy White 提问时间:1/27/2010 最后编辑:Peter MortensenAndy White 更新时间:6/1/2020 访问量:64716
C# DateTime.Now 精度
C# DateTime.Now precision
问:
我只是在进行一些单元测试时遇到了一些意外的DateTime.UtcNow行为。看起来,当您快速连续调用 DateTime.Now/UtcNow 时,它似乎会在比预期更长的时间间隔内返回相同的值,而不是捕获更精确的毫秒增量。
我知道有一个 Stopwatch 类更适合进行精确的时间测量,但我很好奇是否有人可以在 DateTime 中解释这种行为?DateTime.Now 是否有官方精度记录(例如,精确到 50 毫秒以内?为什么 DateTime.Now 的精确度低于大多数 CPU 时钟可以处理的精度?也许它只是为最低公分母 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();
}
答:
此属性的解析 取决于系统计时器。
他们还声称 Windows NT 3.5 及更高版本上的近似分辨率为 10 毫秒:)
值得一提的是,除了实际检查 .NET 源代码之外,Eric Lippert 还对这个 SO 问题发表了评论,称 DateTime 仅精确到大约 30 毫秒。用他的话说,纳秒级精度不高的原因是它“不需要”。
评论
DateTime 的精度在某种程度上特定于运行它的系统。精度与上下文切换的速度有关,它往往在 15 或 16 毫秒左右(在我的系统上,实际上与我的测试相比大约是 14 毫秒,但我见过一些笔记本电脑的精度接近 35-40 毫秒。
Peter Bromberg 写了一篇关于 C# 中高精度代码时序的文章,讨论了这一点。
评论
在 MSDN 中,您会发现它在所有 NT 操作系统上的分辨率约为 10 毫秒。DateTime.Now
实际精度取决于硬件。使用 QueryPerformanceCounter
可以获得更高的精度。
为什么 DateTime.Now 的精确度低于大多数 CPU 时钟可以处理的精度?
一个好的时钟应该既精确又准确;这些是不同的。正如一个老笑话所说,停止的时钟每天精确两次,慢一分钟的时钟在任何时候都不准确。但是慢一分钟的时钟总是精确到最接近的分钟,而停止的时钟根本没有有用的精度。
为什么 DateTime 要精确到微秒,比如说一微秒,而它不可能精确到微秒?大多数人没有任何精确到微秒的官方时间信号的来源。因此,在精度的小数点后给出六位数字,其中最后五位是垃圾,这将是在撒谎。
请记住,DateTime 的用途是表示日期和时间。高精度计时根本不是 DateTime 的目的;正如你所注意到的,这就是秒表的目的。DateTime 的用途是表示日期和时间,以便向用户显示当前时间、计算到下周二的天数等。
简而言之,“现在几点?”和“花了多长时间?”是完全不同的问题;不要使用旨在回答一个问题的工具来回答另一个问题。
谢谢你的问题;这将是一篇很好的博客文章!:-)
评论
我想要一个精确的Datetime.Now :),所以我做了这个:
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); } }
}
评论
此属性的分辨率取决于系统计时器,该计时器 取决于底层操作系统。它往往在 0.5 之间 和 15 毫秒。
因此,在短时间间隔内(例如在循环中)重复调用 Now 属性可能会返回相同的值。
评论