我写了一个函数
toBeautyString(epoch) : String
Run Code Online (Sandbox Code Playgroud)
给出一个epoch
,返回一个字符串,显示从现在开始的小时和分钟的相对时间
例如:
// 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"
Run Code Online (Sandbox Code Playgroud)
我现在想要将此功能扩展到月份和年份,因此它将能够打印:
2 years, 1 month, 3 days and 1 hour ago
Run Code Online (Sandbox Code Playgroud)
只有没有任何外部库的epoch.此功能的目的是为用户提供更好的方式来显示过去的时间.
我发现这个:计算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";
}
}
Run Code Online (Sandbox Code Playgroud)
认识到这是两个不同的问题是有帮助的:1)将时间分割成不同单位的各个块;2) 格式化块并使用您选择的逗号、连词等将它们连接在一起。这样,您就可以将文本格式化逻辑与时间计算逻辑分开。
#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
Run Code Online (Sandbox Code Playgroud)
该解决方案对于现实生活中的年份有些不准确,因为它假设一年由 12 个月组成,每个月长 30 天。这是一个必要的抽象,否则你必须考虑不同的月份长度、闰日和夏令时等等。使用这种方法,你每年会损失大约 3.75 天,这还不错如果您只是用它来可视化时间跨度的大小。