Skip to content

Commit

Permalink
solve(codewars): Human readable duration format [4 kyu]
Browse files Browse the repository at this point in the history
  • Loading branch information
jestenough committed Aug 20, 2023
1 parent 78d30c1 commit 59d916a
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
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)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module src

go 1.21
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)
}

0 comments on commit 59d916a

Please sign in to comment.