diff --git a/duration/time.go b/duration/time.go new file mode 100644 index 0000000..f560a2a --- /dev/null +++ b/duration/time.go @@ -0,0 +1,61 @@ +package duration + +import ( + "bytes" + "math" + "strings" + "text/template" + "time" + + "github.com/leekchan/gtf" +) + +const defaultDurationFormat = `{{if gt .Years 0}}{{.Years}} year{{.Years|pluralize "s"}}, {{end}}` + + `{{if gt .Days 0}}{{.Days}} day{{.Days|pluralize "s"}}, {{end}}` + + `{{if gt .Hours 0}}{{.Hours}} hour{{.Hours|pluralize "s"}}, {{end}}` + + `{{if gt .Minutes 0}}{{.Minutes}} minute{{.Minutes|pluralize "s"}}, {{end}}` + + `{{if gt .Seconds 0}}{{.Seconds}} second{{.Seconds|pluralize "s"}}{{end}}` + +func HumanizeDuration(in time.Duration) string { + f, err := CustomHumanizeDuration(in, defaultDurationFormat) + if err != nil { + panic(err) + } + return strings.Trim(f, " ,") +} + +func CustomHumanizeDuration(in time.Duration, tpl string) (string, error) { + result := struct{ Years, Days, Hours, Minutes, Seconds int64 }{} + + in = time.Duration(math.Abs(float64(in))) + + for in > 0 { + switch { + case in > 365.25*24*time.Hour: + result.Years = int64(in / (365 * 24 * time.Hour)) + in = in - time.Duration(result.Years)*365*24*time.Hour + case in > 24*time.Hour: + result.Days = int64(in / (24 * time.Hour)) + in = in - time.Duration(result.Days)*24*time.Hour + case in > time.Hour: + result.Hours = int64(in / time.Hour) + in = in - time.Duration(result.Hours)*time.Hour + case in > time.Minute: + result.Minutes = int64(in / time.Minute) + in = in - time.Duration(result.Minutes)*time.Minute + default: + result.Seconds = int64(in / time.Second) + in = 0 + } + } + + tmpl, err := template.New("timeformat").Funcs(template.FuncMap(gtf.GtfFuncMap)).Parse(tpl) + if err != nil { + return "", err + } + + buf := bytes.NewBuffer([]byte{}) + tmpl.Execute(buf, result) + + return buf.String(), nil +} diff --git a/duration/time_test.go b/duration/time_test.go new file mode 100644 index 0000000..ddf9aa0 --- /dev/null +++ b/duration/time_test.go @@ -0,0 +1,35 @@ +package duration + +import ( + "testing" + "time" +) + +func TestCustomFormat(t *testing.T) { + d := 389*24*time.Hour + + 12*time.Hour + + 31*time.Minute + + 54*time.Second + + 346*time.Millisecond + + f := `{{.Years}} - {{.Days}} - {{.Hours}} - {{.Minutes}} - {{.Seconds}}` + e := `1 - 24 - 12 - 31 - 54` + + if s, _ := CustomHumanizeDuration(d, f); s != e { + t.Errorf("Got unexpected result: expected=%q result=%q", e, s) + } +} + +func TestDefaultFormat(t *testing.T) { + d := 389*24*time.Hour + + 12*time.Hour + + 31*time.Minute + + 54*time.Second + + 346*time.Millisecond + + e := `1 year, 24 days, 12 hours, 31 minutes, 54 seconds` + + if s := HumanizeDuration(d); s != e { + t.Errorf("Got unexpected result: expected=%q result=%q", e, s) + } +}