2012-07-13 35 views
8

Tôi đang tạo bộ đếm javascript đếm' giây trước '. Tôi có thời gian của tôi trong một đối tượng JS thời gian, và tôi tìm thấy một đoạn mã chức năng "thời gian khác biệt" ở đây trên tràn ngăn xếp, nhưng nó hiển thị "2 giờ trước". Làm cách nào tôi có thể hiển thị "5 giờ, 10 phút và 37 giây trước".Thời gian mờ Javascript (ví dụ: '10 phút trước ') đó là trong giây chính xác

Dưới đây là những gì tôi đang làm việc với:

Chức năng này chuyển đổi thời gian hiện tại và dấu thời gian của một cái gì đó vào "20 giây" thay vì một ngày khó hiểu:

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'; 
    } 
} 

Và đây là những gì tôi đang sử dụng để "đếm lên" thời gian mỗi giây. Tôi muốn nó để nói "5 giờ, 3 phút, 10 giây" và sau đó 1 giây sau, "5 giờ, 3 phút, 11 giây"

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) 

Các newTime biến là thời gian trong Định dạng ngày javascript UTC. relTime là ở định dạng "giây trước". Khoảng thời gian lặp lại thông qua một loạt các yếu tố dấu thời gian và chọn một phần tử phù hợp cho từng dấu thời gian. Sau đó, nó thêm một giây để thời gian, chuyển đổi nó trở lại vào "thời gian mờ" (giây trước), thay thế html với thời gian mới và ghi lại nó trong giao diện điều khiển.

Làm cách nào để thay đổi "5 giờ trước" thành "5 giờ, 37 phút, 10 giây trước"? Chức năng chênh lệch thời gian cần được sửa đổi.

+0

Tại sao bạn lại khai báo 'var relTime' bên trong setInterval? – ErikE

+0

P.S. Tôi sẽ sử dụng một phương pháp rất khác nhau để tìm đúng mục html. Phải có một thẻ dữ liệu- [cái gì đó] bạn có thể thêm vào mỗi thẻ có thể tương ứng với dấu thời gian thích hợp với đúng html. – ErikE

+0

@ErikE Tôi phải khai báo relTime một lần nữa nếu không nó sẽ luôn có giá trị ban đầu. Và cách sử dụng .attr ('datasomething') tốt hơn .html()? – alt

Trả lời

2

Thay đổi logic sao cho thay vì chỉ tìm đơn vị đo lường lớn nhất duy nhất có thể, nó thực hiện điều gì đó với phần còn lại.

Về cơ bản những gì bạn cần làm là bắt đầu với số gia tăng lớn nhất, tìm giá trị, sau đó trừ nó khỏi tổng số để nhận phần còn lại. Sau đó lặp lại.

Một cái gì đó như thế này có thể, tôi chưa thử nghiệm nó.

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 

Sau đó, chỉ cần tạo chuỗi của bạn khỏi các biến.

+0

Tại sao bạn cần biến số còn lại? – alt

+0

@Jackson, bằng cách sử dụng ví dụ của bạn cho phép nói rằng bạn đã có 5 giờ và 37 phút, bạn không thể tiếp tục làm toán trên giá trị 'elapsed' ban đầu. Nếu không, bạn sẽ nhận được 5 giờ, 337 phút (5 giờ * 60 phút + 37 phút). Vì vậy, bạn lấy giá trị 'elapsed', trừ số giờ bạn có thể nhận được và lưu trữ trong' phần còn lại' để bạn có thể tìm ra số phút còn lại. – Brandon

0

này nên làm như lừa:

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

Output: 8 tháng, 12 ngày, 1 giờ, 45 phút và 47 giây

Điều này có thể đương nhiên được refactored để có một chút ít lặp đi lặp lại . Bạn có thể thử câu trả lời này bằng cách làm việc: http://jsfiddle.net/vawEf/

+0

Nếu tôi đưa vào một cái gì đó với PST, nó trả về một cách chính xác. Tôi có PDT và nó trả về "và 5 giờ trước". BẤT K idea ý tưởng nào để làm cho nó hoạt động với dấu thời gian của tôi? Họ trông như thế này: 'Thu Jul 12 2012 16:57:41 GMT-0700 (PDT)' – alt

6

Đây là một chức năng gần với những gì bạn đang yêu cầu.

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

Kết quả:

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

tôi gọi nó là "ngây thơ" vì nó không thực sự chú ý đến cách con người mà chúng ta tính toán thời gian. Nếu chính xác là "1/1/2013 12:01:00 sáng", so sánh với "1/1/2012 12:01:00 sáng" sẽ mang lại "1 năm, 0 tháng, 0 ngày, 0 giờ, 0 phút , 0 giây trước ". Nhưng nó sẽ không làm điều đó bằng cách mở rộng logic trong hàm bạn đã trình bày, và nó sẽ không làm điều đó trong hàm của tôi (hoặc chức năng của tôi sẽ không sử dụng hàng tháng). Một xấp xỉ tốt hơn năm hơn 365 ngày là 365,24, nhưng điều đó cũng bị bỏ qua.

Tôi đã loại trừ các phần thời gian trống khi bạn yêu cầu, để lại "0 giây" ở mức tối thiểu khi không tìm thấy phần thời gian nào.

Bây giờ, nếu bạn muốn cách tính giống như con người, bạn phải quyết định một số điều. Bạn không thể chỉ sử dụng các ranh giới được vượt qua vì ngày 28 tháng 2 đến ngày 1 tháng 3 không phải là cả tháng. Thứ hai, đây là câu hỏi sẽ giải thích vấn đề thực sự:

  • Bao nhiêu tháng và ngày là ngày 2 tháng 2 đến ngày 31 tháng 3?

Nếu bạn tính từ ngày 2 tháng 2 đến ngày 2 tháng 3 là một tháng thì đó là 1 tháng 29 ngày. Nhưng nếu là từ ngày 2 tháng 1 đến ngày 1 tháng 3 thì sao? Đó là cùng một số ngày trôi qua giữa chúng. Có phải bây giờ là 1 tháng (cho tất cả tháng Tư) + 1 ngày trong tháng 3 + 31 ngày trong tháng 1 trong 1 tháng 32 ngày không? Bạn có muốn tháng của bạn trùng với lịch vật lý để con người có thể quay lại với ngón tay của mình và lấy ngày chính xác không? Đó là khó khăn hơn nhiều so với bạn nghĩ.

Nếu bạn có thể trả lời với các quy tắc hợp lý và đầy đủ về cách bạn sẽ làm "thời gian trôi qua giống như con người" thì có thể tôi có thể viết cho bạn một hàm khác để thực hiện.

Cập nhật

Dưới đây là một chức năng mới mà không tháng, và có 365,24 ngày trong một năm (30,43666666 ngày trong một tháng):

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

Output:

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 

Nó vẫn còn ngây thơ, nhưng nó làm một công việc tốt hơn một chút. Thêm vào đó, nó sẽ hoạt động cho những ngày cũ như B.C. những người. :)

+0

Nó nên ẩn tất cả "0 ____ trước". Tôi nghĩ nếu không thì đó là hoàn hảo. – alt

+0

@JacksonGariety Đã cập nhật. Có ổn không khi cái này không bao gồm tháng? Tôi đang làm việc trên một phiên bản nào. – ErikE

+0

Rất tuyệt! Nó có giấu 0 cái không? Tôi sẽ làm thế nào? – alt

Các vấn đề liên quan