123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- package format
- import (
- "fmt"
- "math"
- "strings"
- "time"
- )
- // HumanDuration returns a human-readable approximation of a duration
- // (eg. "About a minute", "4 hours ago", etc.).
- // Modified version of github.com/docker/go-units.HumanDuration
- func HumanDuration(d time.Duration) string {
- return HumanDurationWithCase(d, true)
- }
- // HumanDurationWithCase returns a human-readable approximation of a
- // duration (eg. "About a minute", "4 hours ago", etc.). but allows
- // you to specify whether the first word should be capitalized
- // (eg. "About" vs. "about")
- func HumanDurationWithCase(d time.Duration, useCaps bool) string {
- seconds := int(d.Seconds())
- switch {
- case seconds < 1:
- if useCaps {
- return "Less than a second"
- }
- return "less than a second"
- case seconds == 1:
- return "1 second"
- case seconds < 60:
- return fmt.Sprintf("%d seconds", seconds)
- }
- minutes := int(d.Minutes())
- switch {
- case minutes == 1:
- if useCaps {
- return "About a minute"
- }
- return "about a minute"
- case minutes < 60:
- return fmt.Sprintf("%d minutes", minutes)
- }
- hours := int(math.Round(d.Hours()))
- switch {
- case hours == 1:
- if useCaps {
- return "About an hour"
- }
- return "about an hour"
- case hours < 48:
- return fmt.Sprintf("%d hours", hours)
- case hours < 24*7*2:
- return fmt.Sprintf("%d days", hours/24)
- case hours < 24*30*2:
- return fmt.Sprintf("%d weeks", hours/24/7)
- case hours < 24*365*2:
- return fmt.Sprintf("%d months", hours/24/30)
- }
- return fmt.Sprintf("%d years", int(d.Hours())/24/365)
- }
- func HumanTime(t time.Time, zeroValue string) string {
- return humanTimeWithCase(t, zeroValue, true)
- }
- func HumanTimeLower(t time.Time, zeroValue string) string {
- return humanTimeWithCase(t, zeroValue, false)
- }
- func humanTimeWithCase(t time.Time, zeroValue string, useCaps bool) string {
- if t.IsZero() {
- return zeroValue
- }
- delta := time.Since(t)
- if delta < 0 {
- return HumanDurationWithCase(-delta, useCaps) + " from now"
- }
- return HumanDurationWithCase(delta, useCaps) + " ago"
- }
- // ExcatDuration returns a human readable hours/minutes/seconds or milliseconds format of a duration
- // the most precise level of duration is milliseconds
- func ExactDuration(d time.Duration) string {
- if d.Seconds() < 1 {
- if d.Milliseconds() == 1 {
- return fmt.Sprintf("%d millisecond", d.Milliseconds())
- }
- return fmt.Sprintf("%d milliseconds", d.Milliseconds())
- }
- var readableDur strings.Builder
- dur := d.String()
- // split the default duration string format of 0h0m0s into something nicer to read
- h := strings.Split(dur, "h")
- if len(h) > 1 {
- hours := h[0]
- if hours == "1" {
- readableDur.WriteString(fmt.Sprintf("%s hour ", hours))
- } else {
- readableDur.WriteString(fmt.Sprintf("%s hours ", hours))
- }
- dur = h[1]
- }
- m := strings.Split(dur, "m")
- if len(m) > 1 {
- mins := m[0]
- switch mins {
- case "0":
- // skip
- case "1":
- readableDur.WriteString(fmt.Sprintf("%s minute ", mins))
- default:
- readableDur.WriteString(fmt.Sprintf("%s minutes ", mins))
- }
- dur = m[1]
- }
- s := strings.Split(dur, "s")
- if len(s) > 0 {
- sec := s[0]
- switch sec {
- case "0":
- // skip
- case "1":
- readableDur.WriteString(fmt.Sprintf("%s second ", sec))
- default:
- readableDur.WriteString(fmt.Sprintf("%s seconds ", sec))
- }
- }
- return strings.TrimSpace(readableDur.String())
- }
|