背景

在做新项目开发, 要计算两个时间点 start_atend_at 之间的时长。 在 Go 项目一个广泛的解决办法是 time.Now() - startTime 来计算这个 Duration,但涉及到 time.Now() 可能会出现一些时间偏差问题,在 Stack Overflow 上找到对这个问题的相关讨论,介绍了一个更精确的时长计算方法, 以下是对着这两个计算方式的总结,同时做下比较。

方法一

常见计算方法:

1
2
3
startAt := time.Now()
yourWork()
duration := time.Since(startAt)

方法二

一种高精度的计算方法:

1
2
3
4
startAt := time.Now()
yourWork()
endAt := time.Now()
duration := endAt.Sub(startAt)

问题分析

这两种方法似乎没有什么区别,都是 结束时间 - 开始时间, 但实际两者的原理和实现有根本上的区别,问题的引入点在于 time.Now() 返回的是当前的系统时间

文中提到了两个点:

  1. 在计算两个点的时间差时, 如果系统时区被修改了,那么计算得到的时长是不准的
  2. 系统时间可以比真实时间快或者慢。 特别是当系统将内部时钟与 NTP 时间服务器同步时,这种情况经常发生。

参考

  1. Correctly measure time duration in Go
  2. Proposal: Monotonic Elapsed Time Measurements in Go
  3. golang计算任意两个时间点之间所覆盖的天数