diff --git a/templates/templates.go b/templates/templates.go index 5a0183358..2a1f11e3a 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -138,7 +138,7 @@ func NewTemplateExpander(text string, name string, data interface{}, timestamp c }, "humanize": func(v float64) string { if v == 0 { - return fmt.Sprintf("%.4g ", v) + return fmt.Sprintf("%.4g", v) } if math.Abs(v) >= 1 { prefix := "" @@ -149,7 +149,7 @@ func NewTemplateExpander(text string, name string, data interface{}, timestamp c prefix = p v /= 1000 } - return fmt.Sprintf("%.4g %s", v, prefix) + return fmt.Sprintf("%.4g%s", v, prefix) } else { prefix := "" for _, p := range []string{"m", "u", "n", "p", "f", "a", "z", "y"} { @@ -159,12 +159,12 @@ func NewTemplateExpander(text string, name string, data interface{}, timestamp c prefix = p v *= 1000 } - return fmt.Sprintf("%.4g %s", v, prefix) + return fmt.Sprintf("%.4g%s", v, prefix) } }, "humanize1024": func(v float64) string { if math.Abs(v) <= 1 { - return fmt.Sprintf("%.4g ", v) + return fmt.Sprintf("%.4g", v) } prefix := "" for _, p := range []string{"ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"} { @@ -174,7 +174,45 @@ func NewTemplateExpander(text string, name string, data interface{}, timestamp c prefix = p v /= 1024 } - return fmt.Sprintf("%.4g %s", v, prefix) + return fmt.Sprintf("%.4g%s", v, prefix) + }, + "humanizeDuration": func(v float64) string { + if v == 0 { + return fmt.Sprintf("%.4gs", v) + } + if math.Abs(v) >= 1 { + sign := "" + if v < 0 { + sign = "-" + v = -v + } + seconds := math.Mod(v, 60) + minutes := (int64(v) / 60) % 60 + hours := (int64(v) / 60 / 60) % 24 + days := (int64(v) / 60 / 60 / 24) + // For days to minutes, we display seconds as an integer. + if days != 0 { + return fmt.Sprintf("%s%dd %dh %dm %.0fs", sign, days, hours, minutes, seconds) + } + if hours != 0 { + return fmt.Sprintf("%s%dh %dm %.0fs", sign, hours, minutes, seconds) + } + if minutes != 0 { + return fmt.Sprintf("%s%dm %.0fs", sign, minutes, seconds) + } + // For seconds, we display 4 significant digts. + return fmt.Sprintf("%s%.4gs", sign, math.Floor(seconds*1000+.5)/1000) + } else { + prefix := "" + for _, p := range []string{"m", "u", "n", "p", "f", "a", "z", "y"} { + if math.Abs(v) >= 1 { + break + } + prefix = p + v *= 1000 + } + return fmt.Sprintf("%.4g%ss", v, prefix) + } }, }, } diff --git a/templates/templates_test.go b/templates/templates_test.go index cef49d601..08917acd7 100644 --- a/templates/templates_test.go +++ b/templates/templates_test.go @@ -24,6 +24,7 @@ import ( type testTemplatesScenario struct { text string output string + input interface{} shouldFail bool html bool } @@ -104,13 +105,27 @@ func TestTemplateExpansion(t *testing.T) { }, { // Humanize. - text: "{{ 0.0 | humanize }}:{{ 1.0 | humanize }}:{{ 1234567.0 | humanize }}:{{ .12 | humanize }}", - output: "0 :1 :1.235 M:120 m", + text: "{{ range . }}{{ humanize . }}:{{ end }}", + input: []float64{0.0, 1.0, 1234567.0, .12}, + output: "0:1:1.235M:120m:", }, { // Humanize1024. - text: "{{ 0.0 | humanize1024 }}:{{ 1.0 | humanize1024 }}:{{ 1048576.0 | humanize1024 }}:{{ .12 | humanize1024}}", - output: "0 :1 :1 Mi:0.12 ", + text: "{{ range . }}{{ humanize1024 . }}:{{ end }}", + input: []float64{0.0, 1.0, 1048576.0, .12}, + output: "0:1:1Mi:0.12:", + }, + { + // HumanizeDuration - seconds. + text: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + input: []float64{0, 1, 60, 3600, 86400, 86400 + 3600, -(86400*2 + 3600*3 + 60*4 + 5)}, + output: "0s:1s:1m 0s:1h 0m 0s:1d 0h 0m 0s:1d 1h 0m 0s:-2d 3h 4m 5s:", + }, + { + // HumanizeDuration - subsecond and fractional seconds. + text: "{{ range . }}{{ humanizeDuration . }}:{{ end }}", + input: []float64{.1, .0001, .12345, 60.1, 60.5, 1.2345, 12.345}, + output: "100ms:100us:123.5ms:1m 0s:1m 0s:1.235s:12.35s:", }, { // Title. @@ -145,7 +160,7 @@ func TestTemplateExpansion(t *testing.T) { for _, s := range scenarios { var result string var err error - expander := NewTemplateExpander(s.text, "test", nil, time, ts) + expander := NewTemplateExpander(s.text, "test", s.input, time, ts) if s.html { result, err = expander.ExpandHTML(nil) } else {