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
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)))
}
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
- 3 回答
- 0 关注
- 157 浏览
添加回答
举报