mirror of https://github.com/k3s-io/k3s
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.2 KiB
117 lines
3.2 KiB
package humanize |
|
|
|
import ( |
|
"fmt" |
|
"math" |
|
"sort" |
|
"time" |
|
) |
|
|
|
// Seconds-based time units |
|
const ( |
|
Day = 24 * time.Hour |
|
Week = 7 * Day |
|
Month = 30 * Day |
|
Year = 12 * Month |
|
LongTime = 37 * Year |
|
) |
|
|
|
// Time formats a time into a relative string. |
|
// |
|
// Time(someT) -> "3 weeks ago" |
|
func Time(then time.Time) string { |
|
return RelTime(then, time.Now(), "ago", "from now") |
|
} |
|
|
|
// A RelTimeMagnitude struct contains a relative time point at which |
|
// the relative format of time will switch to a new format string. A |
|
// slice of these in ascending order by their "D" field is passed to |
|
// CustomRelTime to format durations. |
|
// |
|
// The Format field is a string that may contain a "%s" which will be |
|
// replaced with the appropriate signed label (e.g. "ago" or "from |
|
// now") and a "%d" that will be replaced by the quantity. |
|
// |
|
// The DivBy field is the amount of time the time difference must be |
|
// divided by in order to display correctly. |
|
// |
|
// e.g. if D is 2*time.Minute and you want to display "%d minutes %s" |
|
// DivBy should be time.Minute so whatever the duration is will be |
|
// expressed in minutes. |
|
type RelTimeMagnitude struct { |
|
D time.Duration |
|
Format string |
|
DivBy time.Duration |
|
} |
|
|
|
var defaultMagnitudes = []RelTimeMagnitude{ |
|
{time.Second, "now", time.Second}, |
|
{2 * time.Second, "1 second %s", 1}, |
|
{time.Minute, "%d seconds %s", time.Second}, |
|
{2 * time.Minute, "1 minute %s", 1}, |
|
{time.Hour, "%d minutes %s", time.Minute}, |
|
{2 * time.Hour, "1 hour %s", 1}, |
|
{Day, "%d hours %s", time.Hour}, |
|
{2 * Day, "1 day %s", 1}, |
|
{Week, "%d days %s", Day}, |
|
{2 * Week, "1 week %s", 1}, |
|
{Month, "%d weeks %s", Week}, |
|
{2 * Month, "1 month %s", 1}, |
|
{Year, "%d months %s", Month}, |
|
{18 * Month, "1 year %s", 1}, |
|
{2 * Year, "2 years %s", 1}, |
|
{LongTime, "%d years %s", Year}, |
|
{math.MaxInt64, "a long while %s", 1}, |
|
} |
|
|
|
// RelTime formats a time into a relative string. |
|
// |
|
// It takes two times and two labels. In addition to the generic time |
|
// delta string (e.g. 5 minutes), the labels are used applied so that |
|
// the label corresponding to the smaller time is applied. |
|
// |
|
// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier" |
|
func RelTime(a, b time.Time, albl, blbl string) string { |
|
return CustomRelTime(a, b, albl, blbl, defaultMagnitudes) |
|
} |
|
|
|
// CustomRelTime formats a time into a relative string. |
|
// |
|
// It takes two times two labels and a table of relative time formats. |
|
// In addition to the generic time delta string (e.g. 5 minutes), the |
|
// labels are used applied so that the label corresponding to the |
|
// smaller time is applied. |
|
func CustomRelTime(a, b time.Time, albl, blbl string, magnitudes []RelTimeMagnitude) string { |
|
lbl := albl |
|
diff := b.Sub(a) |
|
|
|
if a.After(b) { |
|
lbl = blbl |
|
diff = a.Sub(b) |
|
} |
|
|
|
n := sort.Search(len(magnitudes), func(i int) bool { |
|
return magnitudes[i].D > diff |
|
}) |
|
|
|
if n >= len(magnitudes) { |
|
n = len(magnitudes) - 1 |
|
} |
|
mag := magnitudes[n] |
|
args := []interface{}{} |
|
escaped := false |
|
for _, ch := range mag.Format { |
|
if escaped { |
|
switch ch { |
|
case 's': |
|
args = append(args, lbl) |
|
case 'd': |
|
args = append(args, diff/mag.DivBy) |
|
} |
|
escaped = false |
|
} else { |
|
escaped = ch == '%' |
|
} |
|
} |
|
return fmt.Sprintf(mag.Format, args...) |
|
}
|
|
|