-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
solve(codewars): Human readable duration format [4 kyu]
- Loading branch information
1 parent
78d30c1
commit 59d916a
Showing
3 changed files
with
98 additions
and
0 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
services/codewars/katas/4_kyu/Human readable duration format/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Human readable duration format | ||
|
||
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. | ||
|
||
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`. | ||
|
||
It is much easier to understand with an example: | ||
|
||
``` | ||
* For seconds = 62, your function should return | ||
"1 minute and 2 seconds" | ||
* For seconds = 3662, your function should return | ||
"1 hour, 1 minute and 2 seconds" | ||
``` | ||
|
||
For the purpose of this Kata, a year is 365 days and a day is 24 hours. | ||
|
||
Note that spaces are important. | ||
|
||
Detailed rules | ||
|
||
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. | ||
|
||
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. | ||
|
||
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. | ||
|
||
Different components have different unit of times. So there is not repeated units like in 5 seconds and 1 second. | ||
|
||
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. | ||
|
||
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. | ||
|
||
[Kata link](https://www.codewars.com/kata/52742f58faf5485cae000b9a) |
3 changes: 3 additions & 0 deletions
3
services/codewars/katas/4_kyu/Human readable duration format/src/go.mod
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module src | ||
|
||
go 1.21 |
61 changes: 61 additions & 0 deletions
61
services/codewars/katas/4_kyu/Human readable duration format/src/solution.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
type timeComponent struct { | ||
value int64 | ||
verboseName string | ||
pluralSuffix string | ||
} | ||
|
||
func FormatDuration(seconds int64) string { | ||
if seconds < 0 { | ||
return "now" | ||
} | ||
|
||
const ( | ||
secondsPerYear = 31536000 | ||
secondsPerDay = 86400 | ||
secondsPerHour = 3600 | ||
secondsPerMinute = 60 | ||
) | ||
years, yearsRemainder := seconds/secondsPerYear, seconds%secondsPerYear | ||
days, hoursRemainder := yearsRemainder/secondsPerDay, yearsRemainder%secondsPerDay | ||
hours, minuteRemainder := hoursRemainder/secondsPerHour, hoursRemainder%secondsPerHour | ||
minutes, secondsRemainder := minuteRemainder/secondsPerMinute, minuteRemainder%secondsPerMinute | ||
|
||
timeComponents := []timeComponent{ | ||
{years, "year", "s"}, | ||
{days, "day", "s"}, | ||
{hours, "hour", "s"}, | ||
{minutes, "minute", "s"}, | ||
{secondsRemainder, "second", "s"}, | ||
} | ||
|
||
var formattedComponents []string | ||
for _, component := range timeComponents { | ||
if formattedValue := formatTimeComponent(component); formattedValue != "" { | ||
formattedComponents = append(formattedComponents, formattedValue) | ||
} | ||
} | ||
|
||
separatedByCommaValues := strings.Join(formattedComponents, ", ") | ||
if lastCommaIndex := strings.LastIndex(separatedByCommaValues, ", "); lastCommaIndex != -1 { | ||
separatedByCommaValues = separatedByCommaValues[:lastCommaIndex] + " and" + separatedByCommaValues[lastCommaIndex+1:] | ||
} | ||
|
||
return separatedByCommaValues | ||
} | ||
|
||
func formatTimeComponent(component timeComponent) string { | ||
if component.value == 0 { | ||
return "" | ||
} else if component.value > 1 { | ||
return fmt.Sprintf("%d %s%s", component.value, component.verboseName, component.pluralSuffix) | ||
} | ||
|
||
return fmt.Sprintf("%d %s", component.value, component.verboseName) | ||
} |