9

「秒前」をカウントする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';   
    }
}

そして、これが私が毎秒時間を「カウントアップ」するために使用しているものです。「5 時間 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 は「秒前」形式です。間隔は一連のタイムスタンプ要素をループし、タイムスタンプごとに正しい要素を選択します。次に、時間に 1 秒を追加し、それを「ファジー時間」(秒前) に変換し、html を新しい時間に置き換えて、コンソールに記録します。

「5 時間前」を「5 時間 37 分 10 秒前」に変更するにはどうすればよいですか? 時差機能を修正する必要があります。

4

3 に答える 3

9

これは、あなたが求めているものに近い機能です。

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 日までは 1 か月ではないため、単に境界を越えて使用することはできません。次に、実際の問題を明らかにする質問があります。

  • 2月2日から3月31日までは何月何日?

2 月 2 日から 3 月 2 日を 1 か月として計算すると、1 か月 29 日になります。しかし、それが 1 月 2 日から 3 月 1 日だったらどうでしょうか。それは、それらの間に経過した日数と同じです。これで 1 か月 (4 月全体) + 3 月の 1 日 + 1 月の 31 日で 1 か月 32 日ですか? 人間が指でさかのぼって正しい日付を取得できるように、月を実際のカレンダーと一致させたいですか? それはあなたが思っているよりずっと難しいことです。

「人間のような経過時間の計算」を行う方法について、賢明で完全なルールで答えることができれば、それを行うための別の関数を書くことができるかもしれません。

アップデート

これは、月を処理する新しい関数で、1 年は 365.24 日 (1 か月は 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) {
      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

それはまだ素朴ですが、少し良い仕事をします。さらに、紀元前の日付のような非常に古い日付でも機能します。:)

于 2012-07-13T23:16:40.480 に答える
2

ロジックを変更して、可能な最大の測定単位を 1 つだけ見つけるのではなく、残りの部分で何かを行うようにします。

基本的に必要なことは、最大の増分から始めて値を見つけ、それを合計から差し引いて残りを取得することです。その後、繰り返します。

このようなものかもしれませんが、私はそれをテストしていません。

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

次に、変数から文字列を作成します。

于 2012-07-13T22:38:40.673 に答える
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/

于 2012-07-13T23:06:48.543 に答える