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))
}
或者您可以使用格式化程序定義新類型,并使用新類型進行打?。?/p>
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條經驗 獲得超14個贊
如果您只關心有效的 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 關注
- 215 瀏覽
添加回答
舉報