time.go 1.38 KB
Newer Older
Patrick Devine's avatar
Patrick Devine committed
1
2
3
4
5
6
7
8
9
package format

import (
	"fmt"
	"math"
	"strings"
	"time"
)

Michael Yang's avatar
Michael Yang committed
10
11
12
// humanDuration returns a human-readable approximation of a
// duration (eg. "About a minute", "4 hours ago", etc.).
func humanDuration(d time.Duration) string {
Patrick Devine's avatar
Patrick Devine committed
13
14
15
16
	seconds := int(d.Seconds())

	switch {
	case seconds < 1:
Michael Yang's avatar
Michael Yang committed
17
		return "Less than a second"
Patrick Devine's avatar
Patrick Devine committed
18
19
20
21
22
23
24
25
26
	case seconds == 1:
		return "1 second"
	case seconds < 60:
		return fmt.Sprintf("%d seconds", seconds)
	}

	minutes := int(d.Minutes())
	switch {
	case minutes == 1:
Michael Yang's avatar
Michael Yang committed
27
		return "About a minute"
Patrick Devine's avatar
Patrick Devine committed
28
29
30
31
32
33
34
	case minutes < 60:
		return fmt.Sprintf("%d minutes", minutes)
	}

	hours := int(math.Round(d.Hours()))
	switch {
	case hours == 1:
Michael Yang's avatar
Michael Yang committed
35
		return "About an hour"
Patrick Devine's avatar
Patrick Devine committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
	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 {
Michael Yang's avatar
Michael Yang committed
50
	return humanTime(t, zeroValue)
Patrick Devine's avatar
Patrick Devine committed
51
52
53
}

func HumanTimeLower(t time.Time, zeroValue string) string {
Michael Yang's avatar
Michael Yang committed
54
	return strings.ToLower(humanTime(t, zeroValue))
Patrick Devine's avatar
Patrick Devine committed
55
56
}

Michael Yang's avatar
Michael Yang committed
57
func humanTime(t time.Time, zeroValue string) string {
Patrick Devine's avatar
Patrick Devine committed
58
59
60
61
62
63
	if t.IsZero() {
		return zeroValue
	}

	delta := time.Since(t)
	if delta < 0 {
Michael Yang's avatar
Michael Yang committed
64
		return humanDuration(-delta) + " from now"
Patrick Devine's avatar
Patrick Devine committed
65
66
	}

Michael Yang's avatar
Michael Yang committed
67
	return humanDuration(delta) + " ago"
Patrick Devine's avatar
Patrick Devine committed
68
}