【每日一题20220830】友好展示持续的时长

:magic_wand: 写一个函数,接收秒数,处理成人类友好的方式格式化持续时间。

该函数必须接受一个非负整数。如果它是零,它只是返回"now" 。否则,持续时间表示为yearsdayshoursminutesseconds 的组合 。

举个例子就更容易理解了:

* 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"

就本题而言,一年是 365 天,一天是 24 小时。

请注意,空格很重要。

细则

生成的表达式由 4 seconds1 year等分量组成,一个正整数和一个有效的时间单位之一,由空格分隔。如果整数大于 1,则时间单位以复数形式使用。

组件由逗号和空格 ( ", " ) 分隔。除了最后一个组件用 " and " 分隔, 就像用英文写的一样。

1 second and 1 year 不是正确的,而 1 year and 1 second 是正确 的。

不同的组件有不同的时间单位。所以 5 seconds and 1 second 这样的重复单位写法是错误的。

如果组件的值恰好为零,则组件根本不会出现。因此,1 minute and 0 seconds 是无效的,应该是1 minute 这样编写。

必须“尽可能”使用一个时间单位。这意味着该函数不应该返回61 seconds ,而是应该返回1 minute and 1 second 。所以不要出现366天、24小时、60分、60秒这样的数据。

题目难度:一般
题目来源:https://www.codewars.com/kata/52742f58faf5485cae000b9a

def format_duration(seconds: int) -> str:
    # your code here

assert format_duration(0) == "now"
assert format_duration(1) == "1 second"
assert format_duration(62) == "1 minute and 2 seconds"
assert format_duration(120) == "2 minutes"
assert format_duration(3600) == "1 hour"
assert format_duration(3662) == "1 hour, 1 minute and 2 seconds"
assert format_duration(15731080) == "182 days, 1 hour, 44 minutes and 40 seconds"
assert format_duration(132030240) == "4 years, 68 days, 3 hours and 4 minutes"
assert format_duration(205851834) == "6 years, 192 days, 13 hours, 3 minutes and 54 seconds"
assert format_duration(253374061) == "8 years, 12 days, 13 hours, 41 minutes and 1 second"
assert format_duration(242062374) == "7 years, 246 days, 15 hours, 32 minutes and 54 seconds"
assert format_duration(101956166) == "3 years, 85 days, 1 hour, 9 minutes and 26 seconds"
assert format_duration(33243586) == "1 year, 19 days, 18 hours, 19 minutes and 46 seconds"

这断言结果确定没有问题?就33243586而言
46+19*60+18*60*60+19*24*60*60+1*366*24*60*60 ?= 33243586

image

看起来挺容易,但对字符串处理是真不简单

import re


def format_duration(seconds: int) -> str:
    def get_time(seconds: int) -> list:
        l2 = []
        return_list = [60 * 60 * 24 * 365, 60 * 60 * 24, 60 * 60, 60, 1]
        xin_li = return_list.copy()
        xin_li.append(seconds)
        xin_li.sort(reverse=True)
        if max(xin_li) == seconds:
            for i in return_list:
                number = seconds // i
                seconds = seconds - i * number
                l2.append(number)
        elif min(xin_li) == seconds:
            l2.append(seconds)
        else:
            seconds_index = xin_li.index(seconds)
            xin_sec = return_list[seconds_index:]
            for i in xin_sec:
                number = seconds // i
                seconds = seconds - i * number
                l2.append(number)
        return l2

    if seconds == 0:
        return "now"
    time_list = get_time(seconds)
    # print(time_list)
    t_dic = {1: lambda: f"{time_list[0]} seconds",
             2: lambda: f"{time_list[0]} minutes and {time_list[1]} seconds",
             3: lambda: f"{time_list[0]} hours, {time_list[1]} minutes and {time_list[2]} seconds",
             4: lambda: f"{time_list[0]} days, {time_list[1]} hours, {time_list[2]} minutes and {time_list[3]} seconds",
             5: lambda: f"{time_list[0]} years, {time_list[1]} days, {time_list[2]} hours, {time_list[3]} minutes and {time_list[4]} seconds"}

    time_str = t_dic[len(time_list)]()
    # print(time_list)
    com = re.compile("(?<!\d)1[^\d]s{0,1}.*?s")
    ti = re.findall(com, time_str)
    for i in ti:
        time_str = time_str.replace(i, i[:-1])
    com_1 = re.compile(",{0,1}[^\d]0.*$")
    time_str = re.sub(com_1, "", time_str)
    if time_str.endswith("and"):
        time_str = time_str[0:-4]
    if "," in time_str and "and" not in time_str:
        time_str = time_str[::-1].replace(",", "dna ", 1)[::-1]
    return time_str


if __name__ == '__main__':
    assert format_duration(0) == "now"
    assert format_duration(1) == "1 second"
    assert format_duration(62) == "1 minute and 2 seconds"
    assert format_duration(120) == "2 minutes"
    assert format_duration(3600) == "1 hour"
    assert format_duration(3662) == "1 hour, 1 minute and 2 seconds"
    assert format_duration(15731080) == "182 days, 1 hour, 44 minutes and 40 seconds"
    assert format_duration(132030240) == "4 years, 68 days, 3 hours and 4 minutes"
    assert format_duration(205851834) == "6 years, 192 days, 13 hours, 3 minutes and 54 seconds"
    assert format_duration(253374061) == "8 years, 12 days, 13 hours, 41 minutes and 1 second"
    assert format_duration(242062374) == "7 years, 246 days, 15 hours, 32 minutes and 54 seconds"
    assert format_duration(101956166) == "3 years, 85 days, 1 hour, 9 minutes and 26 seconds"
    assert format_duration(33243586) == "1 year, 19 days, 18 hours, 19 minutes and 46 seconds"
def format_duration(seconds: int) -> str:
    if seconds <= 0:
        return "now"
    else:
        fcontent = ''
        content = {
            0: 0,
            1: 0,
            2: 0,
            3: 0,
            4: 0
        }
        ltime1 = [365 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60, 1]
        ltime2 = ["year", "day", "hour", "minute", "second"]
        for i in range(len(ltime1)):
            content[i] = seconds // ltime1[i]
            seconds -= content[i] * ltime1[i]
        for j in range(len(ltime2)):
            if content[j] > 1:
                fcontent += str(content[j]) + " " + ltime2[j] + "s" + ", "
            elif content[j] == 1:
                fcontent += str(content[j]) + " " + ltime2[j] + ", "
        fcontent = fcontent[:-2][::-1]
        fcontent = fcontent.replace(",", 'dna ', 1)
        fcontent = fcontent[::-1]
        return fcontent

:joy:只有我一个人写了一堆if语句么

def format_duration(seconds: int) -> str:
    def get_time(x: int) -> dict:
        duration_dict=dict()
        duration = ['year', 'day', 'hour', 'minute', 'second']
        time_list = [365 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60, 1]
        time_res=[]
        for time_item in time_list:
            time_res.append(x//time_item)
            x%=time_item
        for i in range(len(time_res)):
            if time_res[i]>1:
                duration[i]=duration[i]+'s'
            duration_dict[duration[i]]=time_res[i]
        return duration_dict

    time_dict=get_time(seconds)
    if sum(list(time_dict.values()))==0:
        return 'now'
    else:
        time_list=[(key,time_dict[key]) for key in time_dict.keys() if time_dict[key]!=0]
        str_line=', '.join([str(i[1])+' '+i[0] for i in time_list])
        index=str_line.rfind(',')
        if index ==-1:
            return str_line
        else:
            str_line=str_line[:index]+' and'+str_line[index+1:]
            return str_line

assert format_duration(0) == "now"
assert format_duration(1) == "1 second"
assert format_duration(62) == "1 minute and 2 seconds"
assert format_duration(120) == "2 minutes"
assert format_duration(3600) == "1 hour"
assert format_duration(3662) == "1 hour, 1 minute and 2 seconds"
assert format_duration(15731080) == "182 days, 1 hour, 44 minutes and 40 seconds"
assert format_duration(132030240) == "4 years, 68 days, 3 hours and 4 minutes"
assert format_duration(205851834) == "6 years, 192 days, 13 hours, 3 minutes and 54 seconds"
assert format_duration(253374061) == "8 years, 12 days, 13 hours, 41 minutes and 1 second"
assert format_duration(242062374) == "7 years, 246 days, 15 hours, 32 minutes and 54 seconds"
assert format_duration(101956166) == "3 years, 85 days, 1 hour, 9 minutes and 26 seconds"
assert format_duration(33243586) == "1 year, 19 days, 18 hours, 19 minutes and 46 seconds"