限制格式化持续时间中的有效数字

Red*_*ick 4 formatting duration go

我正在计时一些不可预测的 I/O。这段代码

started := time.Now()
time.Sleep(123456789 * time.Nanosecond) // unpredictable process    
fmt.Printf("%v", time.Since(started))
Run Code Online (Sandbox Code Playgroud)

生产

123.456789ms
Run Code Online (Sandbox Code Playgroud)

我喜欢单位刻度(ms、?s、ns 等)的自动选择和打印,因为我事先不知道定时操作是否需要微秒、毫秒或秒才能完成。

我不喜欢精度 - 我宁愿只报告两到三个有效数字。是否有一种简单的方法来限制格式化指令%v或类似指令中的精度?

icz*_*cza 5

前言:我在 中发布了此实用程序github.com/icza/gox,请参阅timex.Round()


我认为没有一种简单的方法,因为当使用默认格式(例如%v)打印时,Duration.String()会调用它来生成字符串表示形式。它返回一个string值,因此小数位数等格式选项不再适用。

控制结果小数位数的一种方法是在打印之前截断或舍入持续时间,使用Duration.Truncate()Duration.Round()

当然,持续时间应该被截断或四舍五入的单位取决于持续时间的值,但逻辑并不那么难:

var divs = []time.Duration{
    time.Duration(1), time.Duration(10), time.Duration(100), time.Duration(1000)}

func round(d time.Duration, digits int) time.Duration {
    switch {
    case d > time.Second:
        d = d.Round(time.Second / divs[digits])
    case d > time.Millisecond:
        d = d.Round(time.Millisecond / divs[digits])
    case d > time.Microsecond:
        d = d.Round(time.Microsecond / divs[digits])
    }
    return d
}
Run Code Online (Sandbox Code Playgroud)

让我们用不同的持续时间来测试它:

ds := []time.Duration{
    time.Hour + time.Second + 123*time.Millisecond, // 1h0m1.123s
    time.Hour + time.Second + time.Microsecond,     // 1h0m1.000001s
    123456789 * time.Nanosecond,                    // 123.456789ms
    123456 * time.Nanosecond,                       // 123.456µs
    123 * time.Nanosecond,                          // 123ns
}

for _, d := range ds {
    fmt.Printf("%-15v", d)
    for digits := 0; digits <= 3; digits++ {
        fmt.Printf("%-15v", round(d, digits))

    }
    fmt.Println()
}
Run Code Online (Sandbox Code Playgroud)

输出将是(在Go Playground上尝试):

duration       0 digits       1 digit        2 digits       3 digits
-----------------------------------------------------------------------
1h0m1.123s     1h0m1s         1h0m1.1s       1h0m1.12s      1h0m1.123s     
1h0m1.000001s  1h0m1s         1h0m1s         1h0m1s         1h0m1s         
123.456789ms   123ms          123.5ms        123.46ms       123.457ms      
123.456µs      123µs          123.5µs        123.46µs       123.456µs      
123ns          123ns          123ns          123ns          123ns       
Run Code Online (Sandbox Code Playgroud)