【CodeWars】Human readable duration format

1.題意

題目鏈接:https://www.codewars.com/kata/52742f58faf5485cae000b9a

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:

TimeFormatter.formatDuration(62)   //returns "1 minute and 2 seconds"
TimeFormatter.formatDuration(3662) //returns "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.

題目意思很簡單,就是給定一個秒數seconds,計算這個seconds的year、day、hour、minute、second,以"1year, 2 days, 1 hour, 1 minute and 2 seconds"這樣形式的字符串返回,其中數值爲0 的部分不顯示,最後一個數值用"and"拼接,如果這個0秒則返回"now"

2.代碼

一開始想的是算出這些值,然後用if else來進行判斷拼接字符串,後來發現需要嵌套的if else太多了,就改爲使用一個隊列,計算過程中把這些數值對應的字符串按year、day、hour、minute、second的順序加入到隊列中,全部計算完成之後一個一個出隊拼接到最終需要返回的字符串中,通過隊列的大小來判斷當前使用逗號拼接還是用"and"拼接

import java.util.LinkedList;
import java.util.Queue;

public class TimeFormatter {  
    public static String formatDuration(int seconds) {
        // your code goes here
        if (seconds == 0) return "now";

        int oneMinute = 60;
        int oneHour = 60 * oneMinute;
        int oneDay = 24 * oneHour;
        int oneYear = 365 * oneDay;

		// 注意這裏不要用PriorityQueue,因爲它是會自動給你排序的,用LinkedList,它也是一個隊列
        Queue<String> queue = new LinkedList<>();

        String result = "";
        int year = seconds / oneYear;
        if (year == 1) queue.add(year + " year"); else if (year > 1) queue.add(year + " years");
        seconds = seconds - year * oneYear;

        int day =  seconds / oneDay;
        if (day == 1) queue.add(day + " day"); else if (day > 1) queue.add(day + " days");
        seconds = seconds - day * oneDay;

        int hour = seconds / oneHour;
        if (hour == 1) queue.add(hour + " hour"); else if (hour > 1) queue.add(hour + " hours");
        seconds = seconds - hour * oneHour;

        int minute = seconds / oneMinute;
        if (minute == 1) queue.add(minute + " minute"); else if (minute > 1) queue.add(minute + " minutes");
        seconds = seconds - minute * oneMinute;

        if (seconds == 1) queue.add(seconds + " second"); else if (seconds > 1) queue.add(seconds + " seconds");

        StringBuilder stringBuilder = new StringBuilder();

        while (!queue.isEmpty()){
            String tmp = queue.poll();
            stringBuilder.append(tmp);
            if (queue.size() > 1){
                stringBuilder.append(", ");
            }else if (queue.size() == 1){
                stringBuilder.append(" and ");
            }
        }

        return stringBuilder.toString();
    }
}

測試用例

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

public class TimeFormatterTest {
    @Test
    public void testFormatDurationExamples() {
        // Example Test Cases
        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));
        assertEquals("1 hour and 1 second", TimeFormatter.formatDuration(3601));
    }
}

另外,有人給出了一種很簡潔的Python寫法,使用了if else表達式,具體可以參考https://segmentfault.com/a/1190000006704096

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章