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

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


started := time.Now()

time.Sleep(123456789 * time.Nanosecond) // unpredictable process    

fmt.Printf("%v", time.Since(started))

生产


123.456789ms

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


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


慕无忌1623718
浏览 120回答 3
3回答

鸿蒙传说

我认为没有简单的方法,因为当使用默认格式(例如%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}让我们用不同的持续时间来测试它: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()}输出将是(在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       

婷婷同学_

%v使用 Duration.String(),因此您必须编写自定义格式函数,例如:func fmtTime(in time.Duration, prec int) string {&nbsp; s := in.String()&nbsp; ix := strings.IndexRune(s, '.')&nbsp; if ix == -1 {&nbsp; &nbsp; return s&nbsp; }&nbsp; unit:=len(s)&nbsp; for i,x:=range s[:ix+1] {&nbsp; &nbsp; &nbsp;if !unicode.IsDigit(x) {&nbsp; &nbsp; &nbsp; &nbsp;unit=i+ix+1&nbsp; &nbsp; &nbsp; &nbsp;break&nbsp; &nbsp; &nbsp;}&nbsp; }&nbsp; if prec == 0 {&nbsp; &nbsp; &nbsp;return s[:ix]+s[unit:]&nbsp; }&nbsp; if prec>len(s)-ix-(len(s)-unit)-1 {&nbsp; &nbsp; &nbsp;prec=len(s)-ix-(len(s)-unit)-1&nbsp; }&nbsp; return s[:ix+prec+1]+s[unit:]}func main() {&nbsp; &nbsp;...&nbsp; &nbsp;fmt.Printf("%v\n", fmtTime(time.Since(started), 3))}或者您可以使用格式化程序定义新类型,并使用新类型进行打印:type FmtDuration time.Durationfunc (d FmtDuration) Format(f fmt.State, c rune) {&nbsp; &nbsp;prec,_ := f.Precision()&nbsp; &nbsp;f.Write([]byte(fmtTime(time.Duration(d), prec)))}func main() {&nbsp; &nbsp;fmt.Printf("%.2v", FmtDuration(time.Since(started)))}

翻翻过去那场雪

如果您只关心有效的 3 位数字:// FormatDuration formats a duration with a precision of 3 digits// if it is less than 100s.func FormatDuration(d time.Duration) string {&nbsp; &nbsp; scale := 100 * time.Second&nbsp; &nbsp; // look for the max scale that is smaller than d&nbsp; &nbsp; for scale > d {&nbsp; &nbsp; &nbsp; &nbsp; scale = scale / 10&nbsp; &nbsp; }&nbsp; &nbsp; return d.Round(scale / 100).String()}func Test_FormatDuration(t *testing.T) {&nbsp; &nbsp; for i := 0; i < 15; i++ {&nbsp; &nbsp; &nbsp; &nbsp; dur := time.Duration(3.455555 * math.Pow(10, float64(i)))&nbsp; &nbsp; &nbsp; &nbsp; t.Logf("%2d&nbsp; %12v&nbsp; %6s", i, dur,&nbsp; FormatDuration(dur))&nbsp; &nbsp; }}//&nbsp; &nbsp; &nbsp; original&nbsp; &nbsp; &nbsp;formatted//&nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3ns&nbsp; &nbsp; &nbsp;3ns//&nbsp; 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 34ns&nbsp; &nbsp; 34ns//&nbsp; 2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;345ns&nbsp; &nbsp;345ns//&nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp;3.455µs&nbsp; 3.46µs//&nbsp; 4&nbsp; &nbsp; &nbsp; 34.555µs&nbsp; 34.6µs//&nbsp; 5&nbsp; &nbsp; &nbsp;345.555µs&nbsp; &nbsp;346µs//&nbsp; 6&nbsp; &nbsp; 3.455555ms&nbsp; 3.46ms//&nbsp; 7&nbsp; &nbsp; 34.55555ms&nbsp; 34.6ms//&nbsp; 8&nbsp; &nbsp; 345.5555ms&nbsp; &nbsp;346ms//&nbsp; 9&nbsp; &nbsp; &nbsp;3.455555s&nbsp; &nbsp;3.46s// 10&nbsp; &nbsp; &nbsp;34.55555s&nbsp; &nbsp;34.6s// 11&nbsp; &nbsp; 5m45.5555s&nbsp; &nbsp;5m46s// 12&nbsp; &nbsp; 57m35.555s&nbsp; 57m36s// 13&nbsp; &nbsp;9h35m55.55s&nbsp; 9h35m56s// 14&nbsp; &nbsp;95h59m15.5s&nbsp; 95h59m16s
打开App,查看更多内容
随时随地看视频慕课网APP