【问题标题】:time.Sub() returns 1 second despite the difference exceeding couple of yearstime.Sub() 返回 1 秒,尽管差异超过了几年
【发布时间】:2020-02-26 12:57:26
【问题描述】:

我正在尝试编写一段代码,该代码将对由于同步引起的系统时间变化做出反应。这是一个在 goroutine 内部运行的相当简单的代码:

var start, end time.Time
var start_ts, end_ts int64
var diff_ts time.Duration
var diff time.Duration

for {
    start = time.Now()
    start_ts = start.Unix()
    fmt.Printf("Now: => %v (%d);\n", start, start_ts)
    time.Sleep(1 * time.Second)
    end = time.Now()
    end_ts = end.Unix()
    fmt.Printf("New Now: %v (%d);\n", end, end_ts)
    diff = end.Sub(start)
    diff_ts = time.Duration(end_ts-start_ts) * time.Second
    fmt.Printf("Measured time duration: %v (%v) %f (%f)\n", diff, diff_ts, diff.Seconds(), diff_ts.Seconds())
}

我的问题是,当我在另一个控制台中更改系统时间时,时间读取正确,但是“原始”时差不正确,我不得不求助于手动构建时差。以下是日志的摘录:

Now: => 2020-02-26 12:29:42.778827718 +0000 UTC m=+21.776791756 (1582720182);
New Now: 2017-01-01 01:02:03.391215325 +0000 UTC m=+22.777003266 (1483232523);
Measured time duration: 1.00021151s (-27635h27m39s) 1.000212 (-99487659.000000)

为什么差异对象返回 1 秒,即使差异明显大于那?

【问题讨论】:

  • 您的预期行为被视为错误,Go fixed it in 1.9 响应this problem
  • 请注意,您可以从时间值中去除单调时钟读数。可以减去 缺少 个单调时钟的两倍,得到钟面值差异,而不是单调时钟差异:因为 t.AddDate(y, m, d), t .Round(d) 和 t.Truncate(d) 是墙上时间计算,它们总是从结果中去除任何单调时钟读数。(时间包文档)

标签: go time difference


【解决方案1】:

go 的时间包同时使用“挂钟”(您要更改的内容)和单调时钟。来自docs

操作系统提供了一个“挂钟”,它受制于 时钟同步的变化,以及“单调时钟”,即 不是。一般规则是挂钟是用来报时的 单调时钟用于测量时间。而不是拆分 API, 在这个包中,时间返回的时间。现在包含一堵墙 时钟读数和单调时钟读数;后来的时间告诉 操作使用挂钟读数,但后来测量时间 运算,特别是比较和减法,使用 单调时钟读数。

[...]

如果时间 t 和 u 都包含单调时钟读数,则使用单调执行操作 t.After(u)、t.Before(u)、t.Equal(u) 和 t.Sub(u)仅时钟读数,忽略挂钟读数。

这是专门为防止发生时钟同步(ntp 等)时的异常应用行为而设计的(并将时钟向后推)。 go 的 time 包确保单调时钟读数总是向前移动(在比较或减法操作时)。

【讨论】:

  • 所以要从根本上回答您的问题,您的应用无需担心主机操作系统时间的变化。同步后日志时间戳可能会向后移动(即时间告诉),但时间计算不受影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多