JavaScriptでカウントダウンの処理は以前に記事を投稿したことがありますが、カウントダウンタイマーで日本以外の国から閲覧した際もある程度考慮したいということがあったので、その際に対応した方法をメモ。
サンプルコード
まずは以前作成した処理をベースに普通に作成してみます。
カウントダウンタイマーを設置する要素を配置して、data属性で期間を設定します。
<p>2022年カタールW杯開催(2022/11/21 日本時間19:00)まで</p> <div data-countdown="2022-11-21-19-00-00"></div>
JavaScriptの基本的な処理は以前と同じですが、期限日をHTML側で設定できるようにして複数でも設置できるようにしています。
// カウントダウンの処理実行 countdown_timer(); /** * カウントダウンタイマーの処理 */ function countdown_timer() { // カウントダウンの対象要素 var $countdown = document.querySelectorAll('[data-countdown]'); // 現在日時の取得 var currentTime = (new Date).getTime(); for (var i = 0; i < $countdown.length; i++) { // 期限日の取得 var g = $countdown[i].dataset.countdown.split('-'); var goal = (new Date(g[0], g[1]-1, g[2], g[3], g[4], g[5])).getTime(); // 現在から期限日までの差を取得 var period = goal - currentTime; // 期限を過ぎていない時 if(period >= 0) { // カウントダウンで使用する値を取得 var cDay = Math.floor(period / (1000 * 60 * 60 * 24)); period -= (cDay * (1000 * 60 * 60 * 24)); var cHour = Math.floor(period / (1000 * 60 * 60)); period -= (cHour * (1000 * 60 * 60)); var cMinute = Math.floor(period / (1000 * 60)); period -= (cMinute * (1000 * 60)); var cSecond = Math.floor(period / (1000)); period -= (cSecond * (1000)); cFlame = Math.floor(period / (10)); var insert = ''; insert += '<span class="d">' + adjust_digits(cDay, 3) + '</span>' + "日"; insert += '<span class="h">' + adjust_digits(cHour, 2) + '</span>' + ":"; insert += '<span class="m">' + adjust_digits(cMinute, 2) + '</span>' + ":"; insert += '<span class="s">' + adjust_digits(cSecond, 2) + '</span>' + ":"; insert += '<span class="f">' + adjust_digits(cFlame, 2) + '</span>' + ""; $countdown[i].innerHTML = insert; // 期限を過ぎた時 } else { $countdown[i].innerHTML = 'fin'; } } setTimeout(countdown_timer, 10); } /** * 0以上の整数の頭に0を追加して、指定した桁数にする * @param {number} num - 桁数を調整する数値 * @param {number} digit - 桁数 */ function adjust_digits(num, digit) { var no = String(num); while(no.length < digit) { no = '0' + no; } return no; }
これでカウントダウンタイマーが実装できました。
カウントダウンタイマーのデモページ
日本からの閲覧であれば上記で問題ないですが、時差のある地域からの閲覧の場合、日本から閲覧した場合とカウントがずれます。
対策として、閲覧している現地の日時を日本の日時に変換した上でカウントダウンで使用するようにしてみます。
// カウントダウンの処理実行 countdown_timer(); /** * カウントダウンタイマーの処理 */ function countdown_timer() { // カウントダウンの対象要素 var $countdown = document.querySelectorAll('[data-countdown]'); // 現地での現在日時の取得 var currentTime = (new Date).getTime(); // 協定世界時に変換 var utc = currentTime + (new Date).getTimezoneOffset()*60*1000; // 日本標準時に変換 var jst = utc + 9*60*60*1000; for (var i = 0; i < $countdown.length; i++) { // 期限日の取得 var g = $countdown[i].dataset.countdown.split('-'); var goal = (new Date(g[0], g[1]-1, g[2], g[3], g[4], g[5])).getTime(); // 現在から期限日までの差を取得 var period = goal - jst; // 期限を過ぎていない時 if(period >= 0) { // カウントダウンで使用する値を取得 var cDay = Math.floor(period / (1000 * 60 * 60 * 24)); period -= (cDay * (1000 * 60 * 60 * 24)); var cHour = Math.floor(period / (1000 * 60 * 60)); period -= (cHour * (1000 * 60 * 60)); var cMinute = Math.floor(period / (1000 * 60)); period -= (cMinute * (1000 * 60)); var cSecond = Math.floor(period / (1000)); period -= (cSecond * (1000)); cFlame = Math.floor(period / (10)); var insert = ''; insert += '<span class="d">' + adjust_digits(cDay, 3) + '</span>' + "日"; insert += '<span class="h">' + adjust_digits(cHour, 2) + '</span>' + ":"; insert += '<span class="m">' + adjust_digits(cMinute, 2) + '</span>' + ":"; insert += '<span class="s">' + adjust_digits(cSecond, 2) + '</span>' + ":"; insert += '<span class="f">' + adjust_digits(cFlame, 2) + '</span>' + ""; $countdown[i].innerHTML = insert; // 期限を過ぎた時 } else { $countdown[i].innerHTML = 'fin'; } } setTimeout(countdown_timer, 10); } /** * 0以上の整数の頭に0を追加して、指定した桁数にする * @param {number} num - 桁数を調整する数値 * @param {number} digit - 桁数 */ function adjust_digits(num, digit) { var no = String(num); while(no.length < digit) { no = '0' + no; } return no; }
主な変更点は12〜15行目で、現地の日時を日本標準時に変換してからカウントダウンで使用するようにしています。
時差を考慮したカウントダウンタイマーのデモページ
これで日本で閲覧した場合と時差のある地域で閲覧した場合の差がでなくなりました。
コメントが承認されるまで時間がかかります。