Javascript模糊时间(例如10分钟前);精确到几秒钟

Javascript模糊时间(例如10分钟前);精确到几秒钟,javascript,jquery,date,time,Javascript,Jquery,Date,Time,我正在制作一个javascript计数器,它计数“秒前”。我在JS时间对象中有我的时间,我在堆栈溢出上发现了一个“时间差”函数片段,但它显示为“2小时前”。如何让它显示“5小时10分37秒前” 以下是我的工作内容: 此函数用于将当前时间和某物的时间戳转换为“20秒前”,而不是神秘的日期: function timeDifference(current, previous) { var msPerMinute = 60 * 1000; var msPerHour = msPerMi

我正在制作一个javascript计数器,它计数“秒前”。我在JS时间对象中有我的时间,我在堆栈溢出上发现了一个“时间差”函数片段,但它显示为“2小时前”。如何让它显示“5小时10分37秒前”

以下是我的工作内容:

此函数用于将当前时间和某物的时间戳转换为“20秒前”,而不是神秘的日期:

function timeDifference(current, previous) {
    var msPerMinute = 60 * 1000;
    var msPerHour = msPerMinute * 60;
    var msPerDay = msPerHour * 24;
    var msPerMonth = msPerDay * 30;
    var msPerYear = msPerDay * 365;

    var elapsed = current - previous;

    if (elapsed < msPerMinute) {
         return Math.round(elapsed/1000) + ' seconds ago';   
    } else if (elapsed < msPerHour) {
         return Math.round(elapsed/msPerMinute) + ' minutes ago';   
    } else if (elapsed < msPerDay ) {
         return Math.round(elapsed/msPerHour ) + ' hours ago';   
    } else if (elapsed < msPerMonth) {
         return 'approximately ' + Math.round(elapsed/msPerDay) + ' days ago';   
    } else if (elapsed < msPerYear) {
         return 'approximately ' + Math.round(elapsed/msPerMonth) + ' months ago';   
    } else {
         return 'approximately ' + Math.round(elapsed/msPerYear ) + ' years ago';   
    }
}
变量newTime是UTC javascript日期格式的时间。relTime是“秒前”格式。间隔循环遍历一组时间戳元素,并为每个时间戳选择正确的元素。然后,它向时间添加一秒,将其转换回“模糊时间”(秒前),用新时间替换html并将其记录在控制台中


如何将“5小时前”更改为“5小时37分钟10秒前”?需要修改时差函数。

更改逻辑,使其不只是找到一个最大的测量单位,而是对剩余的进行处理

基本上,你需要做的是从最大的增量开始,找到值,然后从总数中减去它,得到余数。然后重复

可能是这样的,我还没有测试过

var elapsed = current - previous;
var remainder = elapsed;

int years;
int months;

years = Math.floor(remainder/msPerYear);
remainder = remainder % msPerYear;

months = Math.floor(remainder/msPerMonth);
remainder = remainder % msPerMonth;

// repeat

然后只需根据变量构建字符串。

这应该可以做到:

var msPerMinute = 60 * 1000;
var msPerHour = msPerMinute * 60;
var msPerDay = msPerHour * 24;
var msPerMonth = msPerDay * 30;
var msPerYear = msPerDay * 365;

function timeDifference(current, previous) {

var remainder = current - previous;   
var message = "";
var sep = "";

var years = Math.floor(remainder/msPerYear);
remainder = remainder - years * msPerYear;
if (years > 0) {
   message += years + " years";
   sep = ", ";
   console.log(message);
}

var months = Math.floor(remainder/msPerMonth);
remainder = remainder - months * msPerMonth;
if (months > 0) {
   message += sep + months + " months";
   sep = ", ";
   console.log(message);
}

var days = Math.floor(remainder/msPerDay);
remainder = remainder - days * msPerDay;
if (days > 0) {
   message += sep + days + " days";
   sep = ", ";
   console.log(message);
}

var hours = Math.floor(remainder/msPerHour);
remainder = remainder - hours * msPerHour;
if (hours > 0) {
   message += sep + hours + " hours";
   sep = ", ";
   console.log(message);
}

var minutes = Math.floor(remainder/msPerMinute);
remainder = remainder - minutes * msPerMinute;
if (months > 0) {
   message += sep + minutes + " minutes";
   sep = ", ";
   console.log(message);
}

var seconds = Math.floor(remainder/1000);
remainder = remainder - seconds * 1000;
if (months > 0) {
   message += sep + seconds + " seconds";
   sep = ", ";
   console.log(message);
}

message += " ago";

var pos = message.lastIndexOf(',');
message = message.substring(0,pos) + ' and' + message.substring(pos+1)

return message;
};

var output = timeDifference(new Date(2012, 10, 20, 12, 0, 59), new Date(2012, 2, 13, 10, 15, 12));
console.log(output);
输出:8个月12天1小时45分47秒前

var newTime = new Date(data.popular[i].timestamp*1000)
var relTime = timeDifference(new Date(),newTime)

setInterval(function(){
    var theTimeEl = $('.timestamp-large').filter(function(){
        return $(this).html() == relTime
    });
    newTime.setSeconds(newTime.getSeconds() + 1);
    var relTime = timeDifference(new Date(), newTime);
    $(theTimeEl).html(relTime);
    console.log(relTime)
}, 1000)
这当然可以被重构,以减少重复性。 ​
你可以试着让它工作起来:

这是一个接近你要求的函数

var timeparts = [
   {name: 'year', div: 31536000000, mod: 10000},
   {name: 'day', div: 86400000, mod: 365},
   {name: 'hour', div: 3600000, mod: 24},
   {name: 'minute', div: 60000, mod: 60},
   {name: 'second', div: 1000, mod: 60}
];

function timeAgoNaive(comparisonDate) {
   var
      i = 0,
      l = timeparts.length,
      calc,
      values = [],
      interval = new Date().getTime() - comparisonDate.getTime();
   while (i < l) {
      calc = Math.floor(interval / timeparts[i].div) % timeparts[i].mod;
      if (calc) {
         values.push(calc + ' ' + timeparts[i].name + (calc != 1 ? 's' : ''));
      }
      i += 1;
   }
   if (values.length === 0) { values.push('0 seconds'); }
   return values.join(', ') + ' ago';
}

console.log(timeAgoNaive(new Date(Date.parse('Jun 12 2006 11:52:33'))));
console.log(timeAgoNaive(new Date(new Date().getTime() - 3600000)));
console.log(timeAgoNaive(new Date()));
我称之为“天真”,因为它并没有真正关注我们计算时间的人类方式。如果准确地说是“2013年1月1日12:01:00 am”,与“2012年1月1日12:01:00 am”相比,应得出“1年、0个月、0天、0小时、0分钟、0秒前”。但是,通过扩展您介绍的函数中的逻辑,它不会做到这一点,在我的函数中也不会做到这一点(另外,我的函数不会使用几个月)。与365天相比,更好的年近似值为365.24,但这也被忽略

我按照您的要求排除了空时间部分,当没有找到时间部分时,至少留下“0秒”

现在,如果你想要像人类一样的计算方式,你必须决定一些事情。你不能只使用跨越的界限,因为2月28日到3月1日不是一个完整的月份。第二,这里有一个问题将揭示真正的问题:

  • 2月2日到3月31日有多少个月和几天
如果你计算2月2日到3月2日为一个月,那么它是1个月29天。但是如果是1月2日到3月1日呢?这与他们之间经过的天数相同。现在是1个月(整个4月)+3月的1天+1月的31天,1个月的32天吗?你想让你的月份与物理日历重合,这样人类就可以用手指追溯并从中得到正确的日期吗?这比你想象的要困难得多

如果你能用合理和完整的规则来回答,关于你将如何做“类似人类的耗时计算”,那么也许我可以给你写另一个函数来做

更新

这里有一个新函数,它有个月,一年365.24天(一个月30.436666天):

输出:

6 years, 1 month, 1 day, 10 hours, 53 minutes, 44 seconds ago
1 hour ago
now
2 millennia, 9 centuries, 8 decades, 4 months, 26 days, 22 hours, 41 minutes, 47 seconds ago

它仍然很幼稚,但它做得更好一些。此外,它还适用于真正古老的日期,如不列颠哥伦比亚省的日期

为什么要在setInterval中声明
var relTime
?另外,我会使用一种完全不同的方法来查找正确的html项。必须有一个data-[something]标记,您可以添加到每个标记中,使正确的时间戳与正确的html相关联。@ErikE我必须再次声明relTime,否则它将始终具有初始值。如何使用.attr('datasomething')优于.html()?您不必在
setInterval
函数中再次声明
relTime
。你在外面宣布!但无论如何,这里没有足够的信息让我给你提供不同的建议。我需要更多地了解该方案,以及HTML。你能创建一个包含所有片段的JSFIDLE吗?为什么你需要remainer变量?@Jackson,用你的例子来说,假设你有5小时37分钟,你不能继续计算原始的
经过的
值。否则你会得到5小时337分钟(5小时60分钟+37分钟)。因此,你取
已用时间
值,减去你能得到的完整小时数,然后将其存储在
余数
中,这样你就可以计算出剩余的分钟数。如果我输入PST,它会正确返回。我有PDT,它返回“和5小时前”。有没有办法让它和我的时间戳一起工作?它们看起来是这样的:
Thu Jul 12 2012 16:57:41 GMT-0700(PDT)
它应该隐藏所有的“0”之前。“否则我认为那是完美的。”JacksonGariety更新。这个不包括月份可以吗?我正在制作一个版本,非常酷!它是否隐藏了0个?我该怎么做呢?@JacksonGariety当然它隐藏了0部分,带有
if(value)
。看看“1小时前”。它没有分秒组件,所以如果它是20分钟前发布的,它会说“20分钟,37秒前”
var timeparts = [
   {name: 'millenni', div: 31556736000, p: 'a', s: 'um'},
   {name: 'centur', div: 3155673600, p: 'ies', s: 'y'},
   {name: 'decade', div: 315567360},
   {name: 'year', div: 31556736},
   {name: 'month', div: 2629728},
   {name: 'day', div: 86400},
   {name: 'hour', div: 3600},
   {name: 'minute', div: 60},
   {name: 'second', div: 1}
];

function timeAgoNaive2(comparisonDate) {
   var i = 0,
      parts = [],
      interval = Math.floor((new Date().getTime() - comparisonDate.getTime()) / 1000);
   for ( ; interval > 0; i += 1) {
      var value = Math.floor(interval / timeparts[i].div);
      interval = interval - (value * timeparts[i].div);
      if (value) {
         parts.push(value + ' ' + timeparts[i].name + (value !== 1 ? timeparts[i].p || 's' : timeparts[i].s || ''));
      }
   }
   if (parts.length === 0) { return 'now'; }
   return parts.join(', ') + ' ago';
}

console.log(timeAgoNaive2(new Date(Date.parse('Jun 12 2006 11:52:33'))));
console.log(timeAgoNaive2(new Date(new Date().getTime() - 3600000)));
console.log(timeAgoNaive2(new Date()));
console.log(timeAgoNaive2(new Date(-92709631247000)));
6 years, 1 month, 1 day, 10 hours, 53 minutes, 44 seconds ago
1 hour ago
now
2 millennia, 9 centuries, 8 decades, 4 months, 26 days, 22 hours, 41 minutes, 47 seconds ago