algorithm - 以时、日、月、年显示相对时间

标签 algorithm time

我写了一个函数

toBeautyString(epoch) : String

给定一个纪元,返回一个字符串,以小时和分钟显示从现在开始的相对时间

例如:

// epoch: 1346140800 -> Tue, 28 Aug 2012 05:00:00 GMT 
// and now: 1346313600 -> Thu, 30 Aug 2012 08:00:00 GMT
toBeautyString(1346140800) 
-> "2 days and 3 hours ago"

我现在想把这个函数扩展到月和年,这样它就可以打印:

2 years, 1 month, 3 days and 1 hour ago

只有没有任何外部库的时代。 此功能的目的是为用户提供一种更好的方式来可视化过去的时间。

我找到了这个:Calculate relative time in C#但粒度不够。

function toBeautyString(epochNow, epochNow){
    var secDiff = Math.abs(epochNow - epochNow);
    var milliInDay = 1000 * 60 * 60 * 24;
    var milliInHour = 1000 * 60 * 60;

    var nbDays = Math.round(secDiff/milliInDay);
    var nbHour = Math.round(secDiff/milliInHour);

    var relativeHour = (nbDays === 0) ? nbHour : nbHour-(nbDays*24);
    relativeHour %= 24;

    if(nbHour === 0){
        nbDays += 1;
    }else if(nbHour === (nbDays-1)*24){
        nbDays -= 1;
    }

    var dayS = (nbDays > 1) ? "days" : "day";
    var hourS = (relativeHour > 1) ? "hours" : "hour";

    var fullString = "";

    if(nbDays > 0){
        fullString += nbDays + " " + dayS;
        if(relativeHour > 0)
            fullString += " ";
    }

    if(relativeHour > 0){
        fullString += relativeHour + " " + hourS;
    }

    if(epochDate > epochNow){
        return "Will be in " + fullString;
    }else if ((epochDate === epochNow) 
            || (relativeHour === 0 && nbDays === 0)){
        return "Now";
    }else{
        return fullString + " ago";         
    }
}

最佳答案

将此视为两个截然不同的问题是有帮助的:1) 将时间分割成不同单位的各个 block ; 2) 格式化 block 并使用您选择的逗号、连词等将它们连接在一起。这样,您可以将文本格式化逻辑与时间计算逻辑分开。

#converts a time amount into a collection of time amounts of varying size.
#`increments` is a list that expresses the ratio of successive time units
#ex. If you want to split a time into days, hours, minutes, and seconds,
#increments should be [24,60,60]
#because there are 24 hours in a day, 60 minutes in an hour, etc.
#as an example, divideTime(100000, [24,60,60]) returns [1,3,46,40], 
#which is equivalent to 1 day, 3 hours, 46 minutes, 40 seconds
def divideTime(amount, increments):
    #base case: there's no increments, so no conversion is necessary
    if len(increments) == 0:
        return [amount]
    #in all other cases, we slice a bit off of `amount`,
    #give it to the smallest increment,
    #convert the rest of `amount` into the next largest unit, 
    #and solve the rest with a recursive call.
    else:
        conversionRate = increments[-1]
        smallestIncrement = amount % conversionRate
        rest = divideTime(amount / conversionRate, increments[:-1])
        return rest + [smallestIncrement]

def beautifulTime(amount):
    names      = ["year", "month", "day", "hour", "minute", "second"]
    increments = [12,     30,      24,    60,     60]
    ret = []
    times = divideTime(amount, increments)
    for i in range(len(names)):
        time = times[i]
        name = names[i]
        #don't display the unit if the time is zero
        #e.g. we prefer "1 year 1 second" to 
        #"1 year 0 months 0 days 0 hours 0 minutes 1 second"
        if time == 0:
            continue
        #pluralize name if appropriate
        if time != 1:
            name = name + "s"
        ret.append(str(time) + " " + name)
    #there's only one unit worth mentioning, so just return it
    if len(ret) == 1:
        return ret[0]
    #when there are two units, we don't need a comma
    if len(ret) == 2:
        return "{0} and {1}".format(ret[0], ret[1])
    #for all other cases, we want a comma and an "and" before the last unit
    ret[-1] = "and " + ret[-1]
    return ", ".join(ret)

print beautifulTime(100000000)
#output: 3 years, 2 months, 17 days, 9 hours, 46 minutes, and 40 seconds

这个解决方案对于现实生活中的年份来说有些不准确,因为它假设一年由 12 个月组成,每个月有 30 天。这是一个必要的抽象,否则你必须考虑不同的月份长度、闰日和夏令时等等。使用这种方法,你每年将损失大约 3.75 天,这还不错如果您仅使用它来可视化时间跨度的大小。

关于algorithm - 以时、日、月、年显示相对时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12218540/

相关文章:

java - 代码不工作。要求用户输入 2 个字符并在文本文件中搜索以这两个字符开头的字符串

javascript - 有没有有效的方法将数据设置到MapObject?

java - 时间:确定系统显示12小时还是24小时

php - AJAX响应时间

time - 如何使 pthread_cond_timedwait() 对系统时钟操作具有鲁棒性?

vba - 时间识别子上的Excel类型不匹配错误

c++ - 使用分区技术快速排序

algorithm - 赛车拼图

mysql - 检查帖子频率是否为垃圾邮件的好算法

linux - 如何在 Bash 提示符中显示与系统时间不同的时间?