Skip to content

Commit 6859b69

Browse files
authored
Refactor SecToTime() function (#18863)
- Add helper method to reduce redundancy - Expand the scope from displaying days to years - Reduce irrelevance by not displaying small units (hours, minutes, seconds) when bigger ones apply (years)
1 parent b75ad7b commit 6859b69

File tree

3 files changed

+64
-40
lines changed

3 files changed

+64
-40
lines changed

models/issue_tracked_time_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestAddTime(t *testing.T) {
3434
assert.Equal(t, int64(3661), tt.Time)
3535

3636
comment := unittest.AssertExistsAndLoadBean(t, &Comment{Type: CommentTypeAddTimeManual, PosterID: 3, IssueID: 1}).(*Comment)
37-
assert.Equal(t, comment.Content, "1h 1m 1s")
37+
assert.Equal(t, comment.Content, "1 hour 1 minute")
3838
}
3939

4040
func TestGetTrackedTimes(t *testing.T) {
@@ -86,17 +86,17 @@ func TestTotalTimes(t *testing.T) {
8686
assert.Len(t, total, 1)
8787
for user, time := range total {
8888
assert.Equal(t, int64(1), user.ID)
89-
assert.Equal(t, "6m 40s", time)
89+
assert.Equal(t, "6 minutes 40 seconds", time)
9090
}
9191

9292
total, err = TotalTimes(&FindTrackedTimesOptions{IssueID: 2})
9393
assert.NoError(t, err)
9494
assert.Len(t, total, 2)
9595
for user, time := range total {
9696
if user.ID == 2 {
97-
assert.Equal(t, "1h 1m 2s", time)
97+
assert.Equal(t, "1 hour 1 minute", time)
9898
} else if user.ID == 1 {
99-
assert.Equal(t, "20s", time)
99+
assert.Equal(t, "20 seconds", time)
100100
} else {
101101
assert.Error(t, assert.AnError)
102102
}
@@ -107,7 +107,7 @@ func TestTotalTimes(t *testing.T) {
107107
assert.Len(t, total, 1)
108108
for user, time := range total {
109109
assert.Equal(t, int64(2), user.ID)
110-
assert.Equal(t, "1s", time)
110+
assert.Equal(t, "1 second", time)
111111
}
112112

113113
total, err = TotalTimes(&FindTrackedTimesOptions{IssueID: 4})

modules/util/sec_to_time.go

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,64 @@
44

55
package util
66

7-
import "fmt"
7+
import (
8+
"fmt"
9+
"strings"
10+
)
811

9-
// SecToTime converts an amount of seconds to a human-readable string (example: 66s -> 1min 6s)
12+
// SecToTime converts an amount of seconds to a human-readable string. E.g.
13+
// 66s -> 1 minute 6 seconds
14+
// 52410s -> 14 hours 33 minutes
15+
// 563418 -> 6 days 12 hours
16+
// 1563418 -> 2 weeks 4 days
17+
// 3937125s -> 1 month 2 weeks
18+
// 45677465s -> 1 year 6 months
1019
func SecToTime(duration int64) string {
20+
formattedTime := ""
21+
years := duration / (3600 * 24 * 7 * 4 * 12)
22+
months := (duration / (3600 * 24 * 30)) % 12
23+
weeks := (duration / (3600 * 24 * 7)) % 4
24+
days := (duration / (3600 * 24)) % 7
25+
hours := (duration / 3600) % 24
26+
minutes := (duration / 60) % 60
1127
seconds := duration % 60
12-
minutes := (duration / (60)) % 60
13-
hours := duration / (60 * 60) % 24
14-
days := duration / (60 * 60) / 24
1528

16-
var formattedTime string
17-
18-
if days > 0 {
19-
formattedTime = fmt.Sprintf("%dd", days)
20-
}
21-
if hours > 0 {
22-
if formattedTime == "" {
23-
formattedTime = fmt.Sprintf("%dh", hours)
24-
} else {
25-
formattedTime = fmt.Sprintf("%s %dh", formattedTime, hours)
26-
}
27-
}
28-
if minutes > 0 {
29-
if formattedTime == "" {
30-
formattedTime = fmt.Sprintf("%dm", minutes)
31-
} else {
32-
formattedTime = fmt.Sprintf("%s %dm", formattedTime, minutes)
33-
}
29+
// Extract only the relevant information of the time
30+
// If the time is greater than a year, it makes no sense to display seconds.
31+
switch {
32+
case years > 0:
33+
formattedTime = formatTime(years, "year", formattedTime)
34+
formattedTime = formatTime(months, "month", formattedTime)
35+
case months > 0:
36+
formattedTime = formatTime(months, "month", formattedTime)
37+
formattedTime = formatTime(weeks, "week", formattedTime)
38+
case weeks > 0:
39+
formattedTime = formatTime(weeks, "week", formattedTime)
40+
formattedTime = formatTime(days, "day", formattedTime)
41+
case days > 0:
42+
formattedTime = formatTime(days, "day", formattedTime)
43+
formattedTime = formatTime(hours, "hour", formattedTime)
44+
case hours > 0:
45+
formattedTime = formatTime(hours, "hour", formattedTime)
46+
formattedTime = formatTime(minutes, "minute", formattedTime)
47+
default:
48+
formattedTime = formatTime(minutes, "minute", formattedTime)
49+
formattedTime = formatTime(seconds, "second", formattedTime)
3450
}
35-
if seconds > 0 {
36-
if formattedTime == "" {
37-
formattedTime = fmt.Sprintf("%ds", seconds)
38-
} else {
39-
formattedTime = fmt.Sprintf("%s %ds", formattedTime, seconds)
40-
}
51+
52+
// The formatTime() function always appends a space at the end. This will be trimmed
53+
return strings.TrimRight(formattedTime, " ")
54+
}
55+
56+
// formatTime appends the given value to the existing forammattedTime. E.g:
57+
// formattedTime = "1 year"
58+
// input: value = 3, name = "month"
59+
// output will be "1 year 3 months "
60+
func formatTime(value int64, name, formattedTime string) string {
61+
if value == 1 {
62+
formattedTime = fmt.Sprintf("%s1 %s ", formattedTime, name)
63+
} else if value > 1 {
64+
formattedTime = fmt.Sprintf("%s%d %ss ", formattedTime, value, name)
4165
}
4266

4367
return formattedTime

modules/util/sec_to_time_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import (
1111
)
1212

1313
func TestSecToTime(t *testing.T) {
14-
assert.Equal(t, SecToTime(10), "10s")
15-
assert.Equal(t, SecToTime(100), "1m 40s")
16-
assert.Equal(t, SecToTime(1000), "16m 40s")
17-
assert.Equal(t, SecToTime(10000), "2h 46m 40s")
18-
assert.Equal(t, SecToTime(100000), "1d 3h 46m 40s")
19-
assert.Equal(t, SecToTime(1000000), "11d 13h 46m 40s")
14+
assert.Equal(t, SecToTime(66), "1 minute 6 seconds")
15+
assert.Equal(t, SecToTime(52410), "14 hours 33 minutes")
16+
assert.Equal(t, SecToTime(563418), "6 days 12 hours")
17+
assert.Equal(t, SecToTime(1563418), "2 weeks 4 days")
18+
assert.Equal(t, SecToTime(3937125), "1 month 2 weeks")
19+
assert.Equal(t, SecToTime(45677465), "1 year 5 months")
2020
}

0 commit comments

Comments
 (0)