为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕无忌1623718 2023-07-31 15:06:26
我正在对一些不可预测的 I/O 进行计时。这段代码started := time.Now()time.Sleep(123456789 * time.Nanosecond) // unpredictable process    fmt.Printf("%v", time.Since(started))生产123.456789ms我喜欢自动选择和打印单位刻度(ms、μs、ns 等),因为我事先不知道定时操作是否需要微秒、毫秒或秒才能完成。我不喜欢这种精度 - 我宁愿只报告两位或三位有效数字。有没有一种简单的方法来限制格式指令或类似指令的精度%v?
查看完整描述

3 回答

?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

我认为没有简单的方法,因为当使用默认格式(例如%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       


查看完整回答
反对 回复 2023-07-31
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

%v使用 Duration.String(),因此您必须编写自定义格式函数,例如:


func fmtTime(in time.Duration, prec int) string {

  s := in.String()

  ix := strings.IndexRune(s, '.')

  if ix == -1 {

    return s

  }

  unit:=len(s)

  for i,x:=range s[:ix+1] {

     if !unicode.IsDigit(x) {

       unit=i+ix+1

       break

     }

  }

  if prec == 0 {

     return s[:ix]+s[unit:]

  }

  if prec>len(s)-ix-(len(s)-unit)-1 {

     prec=len(s)-ix-(len(s)-unit)-1

  }

  return s[:ix+prec+1]+s[unit:]

}


func main() {

   ...

   fmt.Printf("%v\n", fmtTime(time.Since(started), 3))

}

或者您可以使用格式化程序定义新类型,并使用新类型进行打印:


type FmtDuration time.Duration


func (d FmtDuration) Format(f fmt.State, c rune) {

   prec,_ := f.Precision()

   f.Write([]byte(fmtTime(time.Duration(d), prec)))

}


func main() {

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

}


查看完整回答
反对 回复 2023-07-31
?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

如果您只关心有效的 3 位数字:


// FormatDuration formats a duration with a precision of 3 digits

// if it is less than 100s.

func FormatDuration(d time.Duration) string {

    scale := 100 * time.Second

    // look for the max scale that is smaller than d

    for scale > d {

        scale = scale / 10

    }

    return d.Round(scale / 100).String()

}


func Test_FormatDuration(t *testing.T) {

    for i := 0; i < 15; i++ {

        dur := time.Duration(3.455555 * math.Pow(10, float64(i)))

        t.Logf("%2d  %12v  %6s", i, dur,  FormatDuration(dur))

    }

}

//      original     formatted

//  0           3ns     3ns

//  1          34ns    34ns

//  2         345ns   345ns

//  3       3.455µs  3.46µs

//  4      34.555µs  34.6µs

//  5     345.555µs   346µs

//  6    3.455555ms  3.46ms

//  7    34.55555ms  34.6ms

//  8    345.5555ms   346ms

//  9     3.455555s   3.46s

// 10     34.55555s   34.6s

// 11    5m45.5555s   5m46s

// 12    57m35.555s  57m36s

// 13   9h35m55.55s  9h35m56s

// 14   95h59m15.5s  95h59m16s


查看完整回答
反对 回复 2023-07-31
  • 3 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信