1diff --git a/pkg/humanize/times.go b/pkg/humanize/times.go
2new file mode 100644
3index 0000000000000000000000000000000000000000..1bd51669b320a0f01dbbf1f49bf45241e6c58253
4--- /dev/null
5+++ b/pkg/humanize/times.go
6@@ -0,0 +1,141 @@
7+// This code includes software originally developed by Dustin Sallings.
8+//
9+// Copyright (c) 2005-2008 Dustin Sallings <dustin@spy.net>
10+//
11+// Permission is hereby granted, free of charge, to any person obtaining a copy
12+// of this software and associated documentation files (the "Software"), to deal
13+// in the Software without restriction, including without limitation the rights
14+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+// copies of the Software, and to permit persons to whom the Software is
16+// furnished to do so, subject to the following conditions:
17+//
18+// The above copyright notice and this permission notice shall be included in
19+// all copies or substantial portions of the Software.
20+//
21+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+// SOFTWARE.
28+//
29+//<http://www.opensource.org/licenses/mit-license.php>
30+
31+package humanize
32+
33+import (
34+ "fmt"
35+ "math"
36+ "sort"
37+ "time"
38+)
39+
40+// Seconds-based time units
41+const (
42+ Day = 24 * time.Hour
43+ Week = 7 * Day
44+ Month = 30 * Day
45+ Year = 12 * Month
46+ LongTime = 37 * Year
47+)
48+
49+// Time formats a time into a relative string.
50+//
51+// Time(someT) -> "3 weeks ago"
52+func Time(then time.Time) string {
53+ return RelTime(then, time.Now(), "ago", "from now")
54+}
55+
56+// A RelTimeMagnitude struct contains a relative time point at which
57+// the relative format of time will switch to a new format string. A
58+// slice of these in ascending order by their "D" field is passed to
59+// CustomRelTime to format durations.
60+//
61+// The Format field is a string that may contain a "%s" which will be
62+// replaced with the appropriate signed label (e.g. "ago" or "from
63+// now") and a "%d" that will be replaced by the quantity.
64+//
65+// The DivBy field is the amount of time the time difference must be
66+// divided by in order to display correctly.
67+//
68+// e.g. if D is 2*time.Minute and you want to display "%d minutes %s"
69+// DivBy should be time.Minute so whatever the duration is will be
70+// expressed in minutes.
71+type RelTimeMagnitude struct {
72+ D time.Duration
73+ Format string
74+ DivBy time.Duration
75+}
76+
77+var defaultMagnitudes = []RelTimeMagnitude{
78+ {time.Second, "now", time.Second},
79+ {2 * time.Second, "1 second %s", 1},
80+ {time.Minute, "%d seconds %s", time.Second},
81+ {2 * time.Minute, "1 minute %s", 1},
82+ {time.Hour, "%d minutes %s", time.Minute},
83+ {2 * time.Hour, "1 hour %s", 1},
84+ {Day, "%d hours %s", time.Hour},
85+ {2 * Day, "1 day %s", 1},
86+ {Week, "%d days %s", Day},
87+ {2 * Week, "1 week %s", 1},
88+ {Month, "%d weeks %s", Week},
89+ {2 * Month, "1 month %s", 1},
90+ {Year, "%d months %s", Month},
91+ {18 * Month, "1 year %s", 1},
92+ {2 * Year, "2 years %s", 1},
93+ {LongTime, "%d years %s", Year},
94+ {math.MaxInt64, "a long while %s", 1},
95+}
96+
97+// RelTime formats a time into a relative string.
98+//
99+// It takes two times and two labels. In addition to the generic time
100+// delta string (e.g. 5 minutes), the labels are used applied so that
101+// the label corresponding to the smaller time is applied.
102+//
103+// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier"
104+func RelTime(a, b time.Time, albl, blbl string) string {
105+ return CustomRelTime(a, b, albl, blbl, defaultMagnitudes)
106+}
107+
108+// CustomRelTime formats a time into a relative string.
109+//
110+// It takes two times two labels and a table of relative time formats.
111+// In addition to the generic time delta string (e.g. 5 minutes), the
112+// labels are used applied so that the label corresponding to the
113+// smaller time is applied.
114+func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string {
115+ lbl := albl
116+ diff := b.Sub(a)
117+
118+ if a.After(b) {
119+ lbl = blbl
120+ diff = a.Sub(b)
121+ }
122+
123+ n := sort.Search(len(magnitudes), func(i int) bool {
124+ return magnitudes[i].D > diff
125+ })
126+
127+ if n >= len(magnitudes) {
128+ n = len(magnitudes) - 1
129+ }
130+ mag := magnitudes[n]
131+ args := []interface{}{}
132+ escaped := false
133+ for _, ch := range mag.Format {
134+ if escaped {
135+ switch ch {
136+ case 's':
137+ args = append(args, lbl)
138+ case 'd':
139+ args = append(args, diff/mag.DivBy)
140+ }
141+ escaped = false
142+ } else {
143+ escaped = ch == '%'
144+ }
145+ }
146+ return fmt.Sprintf(mag.Format, args...)
147+}