## The challenge#

Your task in order to complete this challenge 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:

``````//returns "1 minute and 2 seconds"
TimeFormatter.formatDuration(62)

//returns "1 hour, 1 minute and 2 seconds"
TimeFormatter.formatDuration(3662)
``````

For the purpose of this challenge, 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.

## The solution in Java code#

Option 1:

``````import java.util.Arrays;
import java.util.stream.*;
public class TimeFormatter {
public static String formatDuration(int seconds) {
return seconds == 0 ? "now" :
Arrays.stream(
new String[]{
formatTime("year",  (seconds / 31536000)),
formatTime("day",   (seconds / 86400)%365),
formatTime("hour",  (seconds / 3600)%24),
formatTime("minute",(seconds / 60)%60),
formatTime("second",(seconds%3600)%60)})
.filter(e->e!="")
.collect(Collectors.joining(", "))
.replaceAll(", (?!.+,)", " and ");
}
public static String formatTime(String s, int time){
return time==0 ? "" : Integer.toString(time)+ " " + s + (time==1?"" : "s");
}
}
``````

Option 2:

``````public class TimeFormatter {

public static String formatDuration(int seconds) {
String res = "";
int[] units = new int[] {31536000, 86400, 3600, 60, 1};
String[] labels = new String[] {"year", "day", "hour", "minute", "second"};

if (seconds == 0) return "now";

for (int i = 0; i < 5; i++) {
if (seconds >= units[i]) {
int q = seconds / units[i];
seconds = seconds % units[i];
res += (res.equals("") ? "" : (seconds == 0 ? " and " : ", "))
+ q + " " + labels[i] + (q > 1 ? "s" : "");
}
}
return res;
}
}
``````

Option 3:

``````import java.util.*;
public class TimeFormatter {
private static final String[] TIME_WORDS =
{
" years",
" days",
" hours",
" minutes",
" seconds"
};

public static String formatDuration(int seconds) {
if(seconds == 0)
return "now";

int[] timeUnits =
{
seconds/(60*60*24*365),
(seconds/(60*60*24))%365,
(seconds/(60*60))%24,
(seconds/60)%60,
seconds%60
};

List<String> timeElements = new ArrayList<>();
for(int i=0; i<timeUnits.length; i++) {
if(timeUnits[i] != 0)
}

StringBuilder result = new StringBuilder();
for(int i=0; i<timeElements.size(); i++) {
result.append(timeElements.get(i) + getSeparator(i, timeElements.size()));
}

return result.toString();
}

private static String getTimeWord(int timeUnit, String timeWord) {
if(timeUnit == 1)
return timeWord.substring(0, timeWord.length()-1);

return timeWord;
}

private static String getSeparator(int idx, int sz) {
String separator = "";

if(idx < sz-2)
separator = ", ";
else if(idx == sz-2)
separator = " and ";

return separator;
}
}
``````

## Test cases to validate our solution#

``````import org.junit.Test;
import static org.junit.Assert.*;

public class TimeFormatterTest {
@Test
public void exampleTests() {
assertEquals("1 second", TimeFormatter.formatDuration(1));
assertEquals("1 minute and 2 seconds", TimeFormatter.formatDuration(62));
assertEquals("2 minutes", TimeFormatter.formatDuration(120));
assertEquals("1 hour", TimeFormatter.formatDuration(3600));
assertEquals("1 hour, 1 minute and 2 seconds", TimeFormatter.formatDuration(3662));
}
}
``````