英文:
How to get monotonic part of time.Time in Go
问题
我目前正在处理时间戳,并且我想将单调时钟读取部分存储在一个变量中。
假设我有这样的时间戳:2022-03-31 10:20:26.370463 +0200 CEST m=+0.007725255
,我想要获取m=+0.007725255
部分并存储在一个不同的变量中,或者至少获取+0.007725255
部分。在Go语言中,有什么惯用的方法可以实现这个目标?
英文:
am currently working with timestamps and I would like to store in a variable the monotonic clock reading section.
Let's say that I have this: 2022-03-31 10:20:26.370463 +0200 CEST m=+0.007725255
then I would like to get m=+0.007725255
in a different var, or at least the +0.007725255
section. What is the idiomatic way in Go to get it?
答案1
得分: 2
Go的time.Time
类型存储了两个时间戳:
- 墙上时钟时间
- 自进程启动以来的单调持续时间(可选,通过
time.Now
获取)
m=+0.007725255
表示自进程启动以来的单调持续时间(当它存在于time.Time
中时)。
Go通过在初始化期间记录time.startNano
时间戳(非公开)来计算这个偏移量。time.Now
使用startNano
来计算存储在time.Time
中的单调持续时间。由于通常不需要直接检索此值,因此没有简单的公共API可用。
实际上,你只需在当前进程中减去通过time.Now
生成的两个时间戳,结果就是单调持续时间。如果你需要知道自进程启动以来的持续时间,你应该在初始化期间记录一个启动时间戳。
示例代码中展示了如何使用time.Now
来计算时间间隔和自进程启动以来的持续时间。
输出结果如下:
...example event...
Event start: 2022-04-16 16:54:25.088159496 +1000 AEST m=+0.000079273
Event completed: 2022-04-16 16:54:25.089438935 +1000 AEST m=+0.001358685
=== Not recommended ===
Parsed start offset : 79.273µs
Calculate start offset via startNano: 79.273µs
=== Recommended ===
Example event duration: 1.279412ms
Time since startup 2.016789ms
英文:
A Go time.Time
stores 2 timestamps:
- Wall clock
- Monotonic duration since process start (optional, via
time.Now
)
m=+0.007725255
represents the monotonic duration since the start of the process (when present in a time.Time
).
Go calculates this offset by recording time.startNano
timestamp during initialisation (not public). time.Now
uses startNano
to calculate the monotonic duration stored in time.Time
. There is no simple public API to directly retrieve this value since it should never be needed.
In practice, you should simply subtract 2 timestamps generated via time.Now
in your current process and the result will be the monotonic duration. If you need to know the duration since process startup you should record a startup timestamp during initalisation.
Example:
package main
import (
"errors"
"fmt"
"math"
"strconv"
"strings"
"time"
)
func main() {
t0 := time.Now()
fmt.Println("...example event...")
time.Sleep(time.Millisecond)
t1 := time.Now()
fmt.Println("Event start:", t0)
fmt.Println("Event completed:", t1)
fmt.Println("=== Not recommended ===")
offsetT0, _ := monoOffset(t0)
fmt.Println("Parsed start offset:", offsetT0)
startNano, _ := calculateStartNano()
fmt.Println("Calculate start offset via startNano: ", t0.Sub(startNano))
fmt.Println("=== Recommended ===")
fmt.Println("Example event duration:", t1.Sub(t0))
fmt.Println("Time since startup", time.Since(t0))
}
// You should never need anything below here (code smell).
func monoOffset(t time.Time) (time.Duration, error) {
// Recommend strings.Cut on Go1.18+.
parts := strings.Split(t.String(), " m=")
if len(parts) != 2 {
return 0, errors.New("missing monotonic offset")
}
seconds, err := strconv.ParseFloat(parts[1], 64)
if err != nil {
return 0, err
}
nanos := math.Round(seconds * 1e9)
return time.Duration(nanos), nil
}
func calculateStartNano() (time.Time, error) {
now := time.Now()
offset, err := monoOffset(now)
if err != nil {
return time.Time{}, err
}
return now.Add(-offset), nil
}
Outputs:
...example event...
Event start: 2022-04-16 16:54:25.088159496 +1000 AEST m=+0.000079273
Event completed: 2022-04-16 16:54:25.089438935 +1000 AEST m=+0.001358685
=== Not recommended ===
Parsed start offset : 79.273µs
Calculate start offset via startNano: 79.273µs
=== Recommended ===
Example event duration: 1.279412ms
Time since startup 2.016789ms
答案2
得分: 0
单调时钟仅用于计算时间差。单调时钟的绝对值是未定义的,你不应该尝试获取它。我认为你真正想要的是从基准时间开始的持续时间。
func init() {
baseTime = time.Now()
}
// NowTimestamp 实际上返回的是从基准时间开始的持续时间
func NowTimestamp() time.Duration {
return time.Now().Sub(baseTime)
}
英文:
The monotonic clock is just used for differences between times. The absolute value of the monotonic clock is undefined and you should not try to get it. I think what you really want for your timestamp is the duration from a base time.
func init() {
baseTime = time.Now()
}
// NowTimestamp returns really just the duration from the base time
func NowTimestamp() time.Duration {
return time.Now().Sub(baseTime)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论