如何在 Go 中获取 time.Time 的单调部分
How to get monotonic part of time.Time in Go
我目前正在处理时间戳,我想将单调时钟读取部分存储在一个变量中。
假设我有这个:2022-03-31 10:20:26.370463 +0200 CEST m=+0.007725255
然后我想在不同的 var 中获得 m=+0.007725255
,或者至少在 +0.007725255
部分。 Go 中惯用的获取方式是什么?
A Go time.Time
存储 2 个时间戳:
- 挂钟
- 自进程启动以来的单调持续时间(可选,通过
time.Now
)
m=+0.007725255
表示自进程开始以来的单调持续时间(当出现在 time.Time
中时)。
Go 通过在初始化期间记录 time.startNano
时间戳(而不是 public)来计算此偏移量。 time.Now
使用 startNano
计算存储在 time.Time
中的单调持续时间。没有简单的 public API 可以直接检索此值,因为永远不需要它。
实际上,您应该简单地减去当前过程中通过 time.Now
生成的 2 个时间戳,结果将是单调持续时间。如果您需要知道自进程启动以来的持续时间,您应该在初始化期间记录启动时间戳。
示例:
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
}
输出:
...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
我目前正在处理时间戳,我想将单调时钟读取部分存储在一个变量中。
假设我有这个:2022-03-31 10:20:26.370463 +0200 CEST m=+0.007725255
然后我想在不同的 var 中获得 m=+0.007725255
,或者至少在 +0.007725255
部分。 Go 中惯用的获取方式是什么?
A Go time.Time
存储 2 个时间戳:
- 挂钟
- 自进程启动以来的单调持续时间(可选,通过
time.Now
)
m=+0.007725255
表示自进程开始以来的单调持续时间(当出现在 time.Time
中时)。
Go 通过在初始化期间记录 time.startNano
时间戳(而不是 public)来计算此偏移量。 time.Now
使用 startNano
计算存储在 time.Time
中的单调持续时间。没有简单的 public API 可以直接检索此值,因为永远不需要它。
实际上,您应该简单地减去当前过程中通过 time.Now
生成的 2 个时间戳,结果将是单调持续时间。如果您需要知道自进程启动以来的持续时间,您应该在初始化期间记录启动时间戳。
示例:
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
}
输出:
...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