I am timing some unpredictable I/O. This code
started := time.Now()
time.Sleep(123456789 * time.Nanosecond) // unpredictable process
fmt.Printf("%v", time.Since(started))
Produces
123.456789ms
I like the automatic selection and printing of unit scale (ms, μs, ns etc) because I don't know in advance whether the timed operation takes microseconds, milliseconds or seconds to complete.
I don't like the precision - I'd prefer to report only two or three significant digits. Is there a simple way to limit the precision in the formatting directive %v
or similar?
Foreword: I released this utility in github.com/icza/gox
, see timex.Round()
.
I don't think there's a simple way because when printed using the default format (e.g. %v
), Duration.String()
is called to produce the string representation. It returns a string
value, so formatting options like number of fraction digits are not applicable anymore.
One way to control the resulting fraction digits is to truncate or round the duration before printing it, using Duration.Truncate()
or Duration.Round()
.
Of course the unit to which the duration should be truncated or rounded to depends on the duration's value, but the logic is not that hard:
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
}
Let's test it with different durations:
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()
}
Output will be (try it on the 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With