go-span

How long something took, only as precisely as a reader needs. time.Duration.String() prints every nanosecond, 1h46m51.360895289s, which is right for a timestamp and noise for a run that took the best part of two hours. span.Format keeps about four significant figures and lets each larger unit that comes in push a smaller one out.

import span "git.bytestone.uk/hum3/go-span"

span.Format(6411360895289) // "1h46m51s"
span.Format(162345678)     // "162.3ms"
span.Days(388)             // "1y23d"

Pure Go, standard library only.

The rule

Span Precision Example
below 1µs whole nanoseconds, the finest unit 162ns
1µs to 1m 4 significant figures 16.23µs, 162.3ms, 1.623s, 16.23s
1m to 1h seconds to one decimal 2m3.5s
1h to 1d whole seconds 1h46m51s
1d to 10d days, hours, minutes 1d4h33m
10d to 1y days, hours 12d4h
1y and up (a year is 365 days) years, days 1y23d

Rounding that carries a span into the next tier is shown at that tier's precision: 59.996s is 1m0s, not 60s. Below a day the output is a Go duration string, so time.ParseDuration reads it back; days and years are not Go units. Trailing zeros go as they do in Go (1.6s, not 1.600s). A negative span is the positive one with a minus sign.

span.Days(n) is for a count whose unit is the day, such as simulated days run: 340d below a year and 1y23d from 365 on, never hours.

Compared with go-humanize

dustin/go-humanize answers a different question. Its Time and RelTime say roughly when, relative to now, in one English unit; go-span says how long, compactly and with the precision kept. go-humanize has no formatter for a duration's length. Here humanize.RelTime(t, t.Add(d), "", "") (v1.1.0) beside span.Format(d):

d.String() span.Format(d) go-humanize
162ns 162ns now
162.345ms 162.3ms now
16.234567s 16.23s 16 seconds
2m3.456s 2m3.5s 2 minutes
1h46m51.360895289s 1h46m51s 1 hour
28h32m40s 1d4h33m 1 day
292h20m0s 12d4h 1 week
9317h0m0s 1y23d 1 year

Use go-humanize for "3 days ago" on a timeline, and its Bytes and Comma for sizes and counts; go-span for a column of how long runs, requests or stages took, where 1 hour against 1 hour 59 minutes matters.