fs: Higher units for ETA - fixes #3221
This commit is contained in:
parent
7b2b396d37
commit
70c6b01f54
4 changed files with 112 additions and 1 deletions
|
@ -172,7 +172,7 @@ func etaString(done, total int64, rate float64) string {
|
|||
if !ok {
|
||||
return "-"
|
||||
}
|
||||
return d.String()
|
||||
return fs.Duration(d).ReadableString()
|
||||
}
|
||||
|
||||
// percent returns a/b as a percentage rounded to the nearest integer
|
||||
|
|
|
@ -19,9 +19,20 @@ func TestETA(t *testing.T) {
|
|||
wantOK bool
|
||||
wantString string
|
||||
}{
|
||||
// Custom String Cases
|
||||
{size: 0, total: 365 * 86400, rate: 1.0, wantETA: 365 * 86400 * time.Second, wantOK: true, wantString: "1y"},
|
||||
{size: 0, total: 7 * 86400, rate: 1.0, wantETA: 7 * 86400 * time.Second, wantOK: true, wantString: "1w"},
|
||||
{size: 0, total: 1 * 86400, rate: 1.0, wantETA: 1 * 86400 * time.Second, wantOK: true, wantString: "1d"},
|
||||
{size: 0, total: 1110 * 86400, rate: 1.0, wantETA: 1110 * 86400 * time.Second, wantOK: true, wantString: "3y2w1d"},
|
||||
{size: 0, total: 15 * 86400, rate: 1.0, wantETA: 15 * 86400 * time.Second, wantOK: true, wantString: "2w1d"},
|
||||
// Composite Custom String Cases
|
||||
{size: 0, total: 1.5 * 86400, rate: 1.0, wantETA: 1.5 * 86400 * time.Second, wantOK: true, wantString: "1d12h"},
|
||||
{size: 0, total: 95000, rate: 1.0, wantETA: 95000 * time.Second, wantOK: true, wantString: "1d2h23m20s"},
|
||||
// Standard Duration String Cases
|
||||
{size: 0, total: 100, rate: 1.0, wantETA: 100 * time.Second, wantOK: true, wantString: "1m40s"},
|
||||
{size: 50, total: 100, rate: 1.0, wantETA: 50 * time.Second, wantOK: true, wantString: "50s"},
|
||||
{size: 100, total: 100, rate: 1.0, wantETA: 0 * time.Second, wantOK: true, wantString: "0s"},
|
||||
// No String Cases
|
||||
{size: -1, total: 100, rate: 1.0, wantETA: 0, wantOK: false, wantString: "-"},
|
||||
{size: 200, total: 100, rate: 1.0, wantETA: 0, wantOK: false, wantString: "-"},
|
||||
{size: 10, total: -1, rate: 1.0, wantETA: 0, wantOK: false, wantString: "-"},
|
||||
|
|
|
@ -78,6 +78,68 @@ func ParseDuration(age string) (time.Duration, error) {
|
|||
return time.Duration(period), nil
|
||||
}
|
||||
|
||||
// ReadableString parses d into a human readable duration.
|
||||
// Based on https://github.com/hako/durafmt
|
||||
func (d Duration) ReadableString() string {
|
||||
switch d {
|
||||
case DurationOff:
|
||||
return "off"
|
||||
case 0:
|
||||
return "0s"
|
||||
}
|
||||
|
||||
readableString := ""
|
||||
|
||||
// Check for minus durations.
|
||||
if d < 0 {
|
||||
readableString += "-"
|
||||
}
|
||||
|
||||
duration := time.Duration(math.Abs(float64(d)))
|
||||
|
||||
// Convert duration.
|
||||
seconds := int64(duration.Seconds()) % 60
|
||||
minutes := int64(duration.Minutes()) % 60
|
||||
hours := int64(duration.Hours()) % 24
|
||||
days := int64(duration/(24*time.Hour)) % 365 % 7
|
||||
|
||||
// Edge case between 364 and 365 days.
|
||||
// We need to calculate weeks from what is left from years
|
||||
leftYearDays := int64(duration/(24*time.Hour)) % 365
|
||||
weeks := leftYearDays / 7
|
||||
if leftYearDays >= 364 && leftYearDays < 365 {
|
||||
weeks = 52
|
||||
}
|
||||
|
||||
years := int64(duration/(24*time.Hour)) / 365
|
||||
milliseconds := int64(duration/time.Millisecond) -
|
||||
(seconds * 1000) - (minutes * 60000) - (hours * 3600000) -
|
||||
(days * 86400000) - (weeks * 604800000) - (years * 31536000000)
|
||||
|
||||
// Create a map of the converted duration time.
|
||||
durationMap := map[string]int64{
|
||||
"ms": milliseconds,
|
||||
"s": seconds,
|
||||
"m": minutes,
|
||||
"h": hours,
|
||||
"d": days,
|
||||
"w": weeks,
|
||||
"y": years,
|
||||
}
|
||||
|
||||
// Construct duration string.
|
||||
for _, u := range [...]string{"y", "w", "d", "h", "m", "s", "ms"} {
|
||||
v := durationMap[u]
|
||||
strval := strconv.FormatInt(v, 10)
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
readableString += strval + u
|
||||
}
|
||||
|
||||
return readableString
|
||||
}
|
||||
|
||||
// Set a Duration
|
||||
func (d *Duration) Set(s string) error {
|
||||
duration, err := ParseDuration(s)
|
||||
|
|
|
@ -84,6 +84,44 @@ func TestDurationString(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDurationReadableString(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
negative bool
|
||||
in time.Duration
|
||||
want string
|
||||
}{
|
||||
// Edge Cases
|
||||
{false, time.Duration(DurationOff), "off"},
|
||||
// Base Cases
|
||||
{false, time.Duration(0), "0s"},
|
||||
{true, time.Millisecond, "1ms"},
|
||||
{true, time.Second, "1s"},
|
||||
{true, time.Minute, "1m"},
|
||||
{true, (3 * time.Minute) / 2, "1m30s"},
|
||||
{true, time.Hour, "1h"},
|
||||
{true, time.Hour * 24, "1d"},
|
||||
{true, time.Hour * 24 * 7, "1w"},
|
||||
{true, time.Hour * 24 * 365, "1y"},
|
||||
// Composite Cases
|
||||
{true, time.Hour + 2*time.Minute + 3*time.Second, "1h2m3s"},
|
||||
{true, time.Hour * 24 * (365 + 14), "1y2w"},
|
||||
{true, time.Hour*24*4 + time.Hour*3 + time.Minute*2 + time.Second, "4d3h2m1s"},
|
||||
{true, time.Hour * 24 * (365*3 + 7*2 + 1), "3y2w1d"},
|
||||
{true, time.Hour*24*(365*3+7*2+1) + time.Hour*2 + time.Second, "3y2w1d2h1s"},
|
||||
{true, time.Hour*24*(365*3+7*2+1) + time.Second, "3y2w1d1s"},
|
||||
{true, time.Hour*24*(365+7*2+3) + time.Hour*4 + time.Minute*5 + time.Second*6 + time.Millisecond*7, "1y2w3d4h5m6s7ms"},
|
||||
} {
|
||||
got := Duration(test.in).ReadableString()
|
||||
assert.Equal(t, test.want, got)
|
||||
|
||||
// Test Negative Case
|
||||
if test.negative {
|
||||
got = Duration(-test.in).ReadableString()
|
||||
assert.Equal(t, "-"+test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDurationScan(t *testing.T) {
|
||||
var v Duration
|
||||
n, err := fmt.Sscan(" 17m ", &v)
|
||||
|
|
Loading…
Reference in a new issue