猿问

time.Sub() 返回 1 秒,尽管差异超过了几年

我正在尝试编写一段代码,该代码将对由于同步引起的系统时间变化做出反应。这是一个在 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)

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


炎炎设计
浏览 133回答 1
1回答

GCT1015

go 的时间包同时使用“挂钟”(您要更改的内容)和单调时钟。从文档:操作系统提供了一个“挂钟”,它会随着时钟同步的变化而变化,而“单调时钟”则不会。一般规则是挂钟是用来报时的,而单调钟是用来测量时间的。而不是拆分 API,在这个包中 time.Now 返回的时间包含挂钟读数和单调时钟读数;后来的计时操作使用挂钟读数,但后来的时间测量操作,特别是比较和减法,使用单调时钟读数。[...]如果时间 t 和 u 都包含单调时钟读数,则仅使用单调时钟读数执行操作 t.After(u)、t.Before(u)、t.Equal(u) 和 t.Sub(u) ,忽略挂钟读数。这是专门设计用于在发生时钟同步(ntp 等)时防止异常的应用程序行为(并将时钟推回)。go 的 time 包确保单调时钟读数总是向前移动(在比较或减法运算时)。
随时随地看视频慕课网APP

相关分类

Go
我要回答