用途
タイムリミットなどを表示する解説は多いのですが、カウンターが1つだけの場合がほとんどだったので、複数かつ終了時間が別々の場合を想定しています!
単体でなく大量に設置が必要な場合のコードをまとめてみました。
サンプルコード
HTML
<p data-limit="2025-12-01T00:00:00"></p> <p data-limit="2024-06-01T00:00:00"></p> <p data-limit="2025-06-01T00:00:00"></p> <p data-limit=""></p>
JavaScript
let obj = Array.from(document.querySelectorAll('[data-limit]'));
let timeLimitCounter = setInterval(function () {
let now = new Date().getTime();
obj = obj.filter( e => {
let date = new Date(e.dataset.limit).getTime();
if (isNaN(date)) {
e.innerHTML = "error";
return false;
}
let distance = date - now;
if (distance < 0) {
e.innerHTML = "終了しました。";
return false;
}
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
e.innerHTML = days + "<span>日</span>" + hours + "<span>時間</span>" + minutes + "<span>分</span>" + seconds + "<span>秒</span>";
return true;
});
if (obj.length === 0) {
clearInterval(timeLimitCounter);
}
}, 1000);
解説
全体をざっくり解説すると、data属性から要素をすべて取得、1つずつ時間を計算しています。
もし、時間が過ぎていたり空だった場合は配列から除外、配列が0になったら処理を終わらせています。
filter
複数個動かす場合の記述として目立っているのはここかと思います。
1つずつ処理しているのですが、時間が過ぎたり空だったらfalseを返して配列から除外するようにするための記述です。
trueの場合は除外されずに残り続けます。
isNaN
日付フォーマットが無効なものだった場合の処理として入れています。
無効だったら配列から除外することで、以降処理は行われなくなります。
ゼロ埋め
サンプルコードでは、ゼロ埋めなしのyyyyMMddhhmmss形式ですが、hoursとminutesとseconds部分のコードに書き換えるとゼロ埋めありのyyyyMdHms形式になるかと思います。
詳しいコードは下記をご参照ください。
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)).toString().padStart(2, '0'); let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)).toString().padStart(2, '0'); let seconds = Math.floor((distance % (1000 * 60)) / 1000).toString().padStart(2, '0');
以上で解説を終わります。
カウントダウンの処理自体はよくある単体の場合と変わらないです!
具体的に使う機会がありそうなのは、複数商品ある状態でそれぞれ期間限定セール時期が異なる場合など、時間がバラバラで複数のタイマーがないと難しい場合かなと思っています。