.NET Core 中的日期时间精度

Han*_*ans 2 .net c# datetime .net-core

继 Eric Lippert多年前关于 精度的帖子DateTime之后,我在装有 Windows 10 的同一台计算机上对 .netcore 和 .NET Framework 4.5.2 运行了他的测试。

        var n = 1000;
        int i = 0;
        long[] diffs = new long[n];
        while (i++ < n-1)
        {
            if (ticks != DateTime.Now.Ticks)
            {
                var newTicks = DateTime.UtcNow.Ticks;
                var diff = newTicks - ticks;
                diffs[i] = diff;
                ticks = newTicks;
            }
        }
        foreach (var d in diffs)
        {
            if (d == 0)
                Console.WriteLine("same");
            else
                Console.WriteLine(d);

        }
Run Code Online (Sandbox Code Playgroud)

.NET Framework 4.5.2 上的结果符合预期:输出中有一些随机“相同”,这意味着DateTime某些子级别不精确。

然而,.NET core 上的结果完全不同:输出中没有“相同”。没有两个Ticks具有相同的值。

该怎么解释呢?

inq*_*ive 5

解释是,.net 向底层操作系统询问当前时间。操作系统询问底层硬件。在古代,主板上的硬件时钟 (RTC) 每约 15 毫秒更新一次。这个数字是根据美国 60Hz 交流线路频率得出的,电网保持足够准确。请记住,那是计算机“慢”的时代,设计师们试图尽可能地发挥每一点性能。因此,每次有人请求时间时,操作系统都不会咨询 RTC,并传递该值的缓存副本 - 该副本很少更新。

后来,主板不断发展,RTC 变得更加精确。但操作系统和其之上的所有东西并不觉得有必要。请记住,硬件的发展速度远远快于软件,甚至直到今天,消费级软件都浪费了很大一部分原始硬件功能。因此,当.net框架向操作系统请求时间时,即使硬件有能力,它也会返回不精确的数据。准确度确实从 15 毫秒发展到了 1 毫秒以下,但仅此而已。

到了windows 8(server 2012),终于意识到(1)应用程序可以通过更精确的时间做得更好(2)计算机速度很快,所以每次查询RTC不再是问题(3)大量的程序员和程序习惯并且实际上依赖于不精确的时间行为。因此,他们(win 8)继续引入一种新的稍微慢一些的机制来获取最精确的时间数据,但保持原始实现不变。

dot net一直使用旧的、不精确的操作系统功能GetSystemTimeAsFileTime,当win 8中出现新表弟时GetSystemTimePreciseAsFileTime,dot net选择走向后兼容的方式,什么也没做。

Dot net core 是对许多核心功能的全新重写,现在利用了高精度数据源。

编辑

如果当前时间是13:14:15:123456,仍然不能保证物理学家和天文学家所看到的真正的时间。您的计算机不是原子钟。当然也不是一个同步良好的时钟。它唯一的意思是,如果两个事件在不同的时间戳发生,那么一个事件肯定在另一个事件之前发生。在较旧的计算机中,事件(例如日志、文件、数据库 txns 等)的生成率较低,因此顺序事件被分配相同时间戳的可能性很小。这个新的时间系统迎合现代高频率活动,以便您可以将连续事件标记为不同的。尽管如此,对于两个非常接近的事件,总是有可能出现相同的时间戳。这最终是不可避免的。如果您需要纳秒级测量(为什么),您需要不同的工具,例如StopwatchSystem.DateTime