2012-07-13 31 views
8

我正在製作一個JavaScript計數器,計數'秒前'。我有我的時間在一個JS時間對象,並且我在堆棧溢出發現了一個「時間差異」函數代碼片段,但它顯示「2小時前」。我怎樣才能讓它顯示「5小時10分37秒前」。Javascript模糊時間(例如,'10分鐘前')精確秒數

這裏就是我的工作:

該函數將當前時間和事物的時間戳轉換成「進行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'; 
    } 
} 

這裏就是我每秒用於「計數」時間。我想它說「10小時,3分鐘,10秒前」,然後在1秒鐘之後,「5小時,3分鐘,11秒前」

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) 

可變NEWTIME是時間在UTC javascript日期格式。 relTime是以「秒前」格式。間隔循環通過一堆時間戳記元素,併爲每個時間戳選取正確的一個。然後它增加一秒的時間,將其轉換回「模糊時間」(幾秒前),用新時間替換html並將其記錄在控制檯中。

如何將「5小時前」更改爲「5小時37分鐘10秒前」?時差功能需要修改。

+0

爲什麼你要在setInterval內重新聲明'var relTime'? – ErikE 2012-07-13 22:42:08

+0

P.S.我會用一種非常不同的方法來找到正確的html項目。必須有一個數據 - [東西]標籤,您可以添加到每個可以將正確的時間戳與正確的html相關聯。 – ErikE 2012-07-14 02:55:16

+0

@ErikE我必須再次聲明relTime,否則它將始終具有初始值。以及如何使用.attr('datasomething')比.html()更好? – alt 2012-07-14 17:53:45

回答

2

改變邏輯,使其不是隻找到一個最大的測量單位,而是用餘數來做一些事情。

基本上你需要做的是從最大增量開始,找到值,然後從總數中減去以得到餘數。然後重複。

也許這樣的事情,我沒有測試過。

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 

然後只是建立你的字符串變量。

+0

爲什麼你需要剩餘變量? – alt 2012-07-13 23:09:07

+0

@Jackson,使用你的例子可以說你有5小時37分鐘,你不能繼續對原始'elapsed'值進行數學運算。否則,你會得到5小時337分鐘(5小時* 60分鐘+ 37分鐘)。所以你採用'elapsed'值,減去你能夠獲得的完整小時數,並將其存儲在'remaining'中,這樣你就可以計算出剩餘的分鐘數。 – Brandon 2012-07-13 23:52:55

0

這應該做的伎倆:

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秒前

這當然可以進行重構,以少一點重複。 你可以嘗試一下它的工作:http://jsfiddle.net/vawEf/

+0

如果我在PST中放置了某些東西,它會正確返回。我有PDT,它返回「和5小時前」。任何想法都可以使它與我的時間戳一起工作?他們看起來像這樣:'Thu Jul 12 2012 16:57:41 GMT-0700(PDT)' – alt 2012-07-13 23:17:50

6

這是一個函數,它接近你所要求的。

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())); 

結果:

6 years, 33 days, 4 hours, 52 minutes, 22 seconds ago 
1 hour ago 
0 seconds ago 

我把它叫做「幼稚的」,因爲它並沒有真正重視起來,我們計算時間的人的方式。如果是「2013年1月1日12:01:00」,那麼與「2012年1月1日上午12:01:00」相比,「應該產生」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.43666666天一個月):

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) { 
     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 

它仍然天真,但它做得更好一點。此外,它將適用於像B.C這樣真正的舊日期。那些。 :)

+0

它應該隱藏所有「0 ____前」。我認爲否則這是完美的。 – alt 2012-07-13 23:31:22

+0

@JacksonGariety更新。這個不包括幾個月可以嗎?我正在研究一個版本。 – ErikE 2012-07-13 23:46:28

+0

非常酷!它隱藏了0嗎?我會怎麼做呢? – alt 2012-07-14 17:54:50

相關問題