最近看异步课程的代码时,发现代码中基本都使用 DateTime.UtcNow 来测量时间间隔,于是好奇搜了一下这样做的优势。

参考:DateTime.UtcNow is generally preferable to DateTime.Now

在所有非面向用户的场景,例如测量时间间隔、测试超时时间和持久化 DateTime(文件系统或数据库)时都推荐使用 UtcNow。

我们应该只在面向用户的场景中使用 DateTime.Now。因为它包含时区和夏令时信息(DST),可以保证我们向用户展示的时间与他们的挂钟时间相同,用户体验较好。

UtcNow 更快

UtcNow 通常比 Now 快几个数量级,因为 Now 内部首先就是调用 UtcNow,然后用很长时间来计算时区和夏令时信息。

下图是来自 Keyvan 博客的耗时比较图。
DateTime.UtcNow vs DateTime.Now - 图1

Now 有隐患

DST 每年有两次的调整期,那时会出现 1 小时的跳变。

想象一下,凌晨 2 点时你正有一个 5 秒超时的操作在循环里面运行,结果恰好 DST 调整导致时间跳变,本来该在 5 秒后超时的操作直接运行了 1 小时 5 秒!

如何进行精确的时间测量

对于精确的时间间隔测量,应该使用 System.Diagnostics.StopWatch,它使用高精度计时器(QueryPerformanceCounter)。 DateTime.Now 和 DateTime.UtcNow 的精度都非常低 —— 大约 10ms。

对于简单的时间戳,通常直接用 Environment.TickCount 即可,它甚至比 DateTime.UtcNow.Ticks 更快。