Skip to content

Commit 59d916a

Browse files
committed
solve(codewars): Human readable duration format [4 kyu]
1 parent 78d30c1 commit 59d916a

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Human readable duration format
2+
3+
Your task in order to complete this Kata is to write a function which formats a duration, given as a number of seconds, in a human-friendly way.
4+
5+
The function must accept a non-negative integer. If it is zero, it just returns `"now"`. Otherwise, the duration is expressed as a combination of `years`, `days`, `hours`, `minutes` and `seconds`.
6+
7+
It is much easier to understand with an example:
8+
9+
```
10+
* For seconds = 62, your function should return
11+
"1 minute and 2 seconds"
12+
* For seconds = 3662, your function should return
13+
"1 hour, 1 minute and 2 seconds"
14+
```
15+
16+
For the purpose of this Kata, a year is 365 days and a day is 24 hours.
17+
18+
Note that spaces are important.
19+
20+
Detailed rules
21+
22+
The resulting expression is made of components like 4 seconds, 1 year, etc. In general, a positive integer and one of the valid units of time, separated by a space. The unit of time is used in plural if the integer is greater than 1.
23+
24+
The components are separated by a comma and a space (", "). Except the last component, which is separated by " and ", just like it would be written in English.
25+
26+
A more significant units of time will occur before than a least significant one. Therefore, 1 second and 1 year is not correct, but 1 year and 1 second is.
27+
28+
Different components have different unit of times. So there is not repeated units like in 5 seconds and 1 second.
29+
30+
A component will not appear at all if its value happens to be zero. Hence, 1 minute and 0 seconds is not valid, but it should be just 1 minute.
31+
32+
A unit of time must be used "as much as possible". It means that the function should not return 61 seconds, but 1 minute and 1 second instead. Formally, the duration specified by of a component must not be greater than any valid more significant unit of time.
33+
34+
[Kata link](https://www.codewars.com/kata/52742f58faf5485cae000b9a)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module src
2+
3+
go 1.21
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
type timeComponent struct {
9+
value int64
10+
verboseName string
11+
pluralSuffix string
12+
}
13+
14+
func FormatDuration(seconds int64) string {
15+
if seconds < 0 {
16+
return "now"
17+
}
18+
19+
const (
20+
secondsPerYear = 31536000
21+
secondsPerDay = 86400
22+
secondsPerHour = 3600
23+
secondsPerMinute = 60
24+
)
25+
years, yearsRemainder := seconds/secondsPerYear, seconds%secondsPerYear
26+
days, hoursRemainder := yearsRemainder/secondsPerDay, yearsRemainder%secondsPerDay
27+
hours, minuteRemainder := hoursRemainder/secondsPerHour, hoursRemainder%secondsPerHour
28+
minutes, secondsRemainder := minuteRemainder/secondsPerMinute, minuteRemainder%secondsPerMinute
29+
30+
timeComponents := []timeComponent{
31+
{years, "year", "s"},
32+
{days, "day", "s"},
33+
{hours, "hour", "s"},
34+
{minutes, "minute", "s"},
35+
{secondsRemainder, "second", "s"},
36+
}
37+
38+
var formattedComponents []string
39+
for _, component := range timeComponents {
40+
if formattedValue := formatTimeComponent(component); formattedValue != "" {
41+
formattedComponents = append(formattedComponents, formattedValue)
42+
}
43+
}
44+
45+
separatedByCommaValues := strings.Join(formattedComponents, ", ")
46+
if lastCommaIndex := strings.LastIndex(separatedByCommaValues, ", "); lastCommaIndex != -1 {
47+
separatedByCommaValues = separatedByCommaValues[:lastCommaIndex] + " and" + separatedByCommaValues[lastCommaIndex+1:]
48+
}
49+
50+
return separatedByCommaValues
51+
}
52+
53+
func formatTimeComponent(component timeComponent) string {
54+
if component.value == 0 {
55+
return ""
56+
} else if component.value > 1 {
57+
return fmt.Sprintf("%d %s%s", component.value, component.verboseName, component.pluralSuffix)
58+
}
59+
60+
return fmt.Sprintf("%d %s", component.value, component.verboseName)
61+
}

0 commit comments

Comments
 (0)