クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【JS】DateとsetTimeout()で作るカウントダウンタイマー(令和まであと何日?)

平成最後の日に作る、令和まであと何日?カウントダウンタイマーです。JSの組み込みオブジェクトDateと組み込みメソッドsetTimeout()を使います。ふ〜、なんとか間に合った〜。それでは参ります!

【目次】

JSの基本はこちら
※参考:【JSの基本-前編】書ける前に読む!HTML、CSS、JSの書式-4 - クモのようにコツコツと
※参考:【JSの基本-後編】書ける前に読む!HTML、CSS、JSの書式-5 - クモのようにコツコツと

令和カウントダウンタイマー(完成品)

先に完成品です。ドン!

See the Pen reiwa countdown5 by イイダリョウ (@i_ryo) on CodePen.

カウントダウンはもう始まってますね〜。どうやって作ったか。順番に見ていきます。

Dateオブジェクトで現在日時を取得

カウントダウンするには現在日時の取得から始めます。JSには現在日時を取得する組み込みオブジェクトが用意されています。Dateといいます。こちらをご覧ください。

See the Pen reiwa countdown0 by イイダリョウ (@i_ryo) on CodePen.

「今何時でっか?」の下に日時が表示されています。こちらの日時はJSが取得した現在時刻です。

HTMLコード

<p>今何時でっか?</p>

<p class="counter"></p>

要素は2つだけです。下の要素. counterの中身は空っぽです。が、画面上には日時が表示されています。JSで表示しています。

JSコード

//オブジェクト取得
const counter = document.querySelector('.counter');

//今の日時
const d1 = new Date();
  
//テキスト
counter.innerHTML = d1;
  • 変数counter.counterを取得
  • 変数d1newで組み込みオブジェクトDateのインスタンスDate()を作成
  • counterの中身をinnerHTMLd1に書き換え

たったの3行〜♪簡単ですね!なお、インスタンス(new)についてはこちらで解説しています。

※参考:【JS】newとプロトタイプとクラス - クモのようにコツコツと

さてこの表記、なんだか欧米風で日本語では馴染み薄いですね〜。月名が数字じゃなくて英語だったり。GMT+0900 (JST)GMTはグリニッジ標準時間、JSTはジャパン・スタンダード・タイム。時差は+9時間です。

日本語で馴染みのある表記にするには、ここからさらにアレンジが必要です。

.getFullYear()などのメソッドで日時を個別に取得

欧米風の表記を「○年○月○日○時○分○秒」という表記に変更したい。こちらをご覧ください。

See the Pen reiwa countdown1 by イイダリョウ (@i_ryo) on CodePen.

「○年○月○日○時○分○秒」という表記になりましたねー。実現するために先ほど一体になっていた日時を年だけ、月だけ、など個別に取得しています。

JSコードはこちら(HTMLは変更なし)

//オブジェクト取得
const counter = document.querySelector('.counter');

//今の日時
const d1 = new Date();
const d1_Year = d1.getFullYear();
const d1_Month = d1.getMonth() + 1;
const d1_Date = d1.getDate();
const d1_Hour = d1.getHours();
const d1_Minute = d1.getMinutes();
const d1_Second = d1.getSeconds();

//テキスト
counter.innerHTML = d1_Year + "年" +  d1_Month +  "月" + d1_Date + "日" +  d1_Hour + "時" + d1_Minute + "分" + d1_Second + "秒" ;
  • オブジェクト取得、Date()インスタンスまでは変更なし
  • 変数d1_YeargetFullYear()で現在の年を取得(西暦4桁)
  • 変数d1_MonthgetMonth() + 1で現在の月を取得(0からカウント)
  • 変数d1_DategetDate()で現在の日を取得
  • 変数d1_HourgetHours()で現在の時を取得
  • 変数d1_MinutegetMinutes()で現在の分を取得
  • 変数d1_SecondgetSeconds()で現在の秒を取得
  • counterの中には上記で取得した日時の数値と文字列(「年」など)を入れる

メソッド名はだいたい想像がつく名前になっていますね。getFullYear()は西暦の4桁全てを取得するのでフル。getMonth()は0からカウントし始めるので+1します。

表記は見やすくなったのですが、このままだと表示されている日時はページが読み込まれた状態から更新されません。

クリックイベントにして再読み込み

日時表記をページ読み込み時ではなくボタンのクリックイベント時にしたい。こちらをご覧ください。

See the Pen reiwa countdown2 by イイダリョウ (@i_ryo) on CodePen.

「押して」ボタンを押すとその度に最新の日時になります!

HTMLコード

<p>今何時でっか?</p>

<button class="reiwa">押して</button>

<p class="counter"></p>

「今何時でっか?」と. counterのあいだにreiwaボタンを追加。

JSコード

//オブジェクト取得
const reiwa = document.querySelector('.reiwa');
const counter = document.querySelector('.counter');

//あと何日メソッド
function nanNichi(){

//今の日時
const d1 = new Date();
const d1_Year = d1.getFullYear();
const d1_Month = d1.getMonth() + 1;
const d1_Date = d1.getDate();
const d1_Hour = d1.getHours();
const d1_Minute = d1.getMinutes();
const d1_Second = d1.getSeconds();

//テキスト
counter.innerHTML = d1_Year + "年" +  d1_Month +  "月" + d1_Date + "日" +  d1_Hour + "時" + d1_Minute + "分" + d1_Second +  "秒";
}

//クリックイベント
reiwa.addEventListener('click', nanNichi, false);
  • 変数reiwa. reiwa要素を取得(変数counterは変更なし)
  • 関数nanNichi()の中に日時取得とテキスト表示の命令を入れる
  • reiwaにクリックイベントを設定。nanNichi関数を実行。

これで最新の日時が取得できるようになりました。次に本来の目的、令和まであとどのくらい?カウンターを作りたい。

Date()の中にターゲット日時を入れて時差を出す

令和カウンターに向けた第一歩。こちらです。

See the Pen reiwa countdown3 by イイダリョウ (@i_ryo) on CodePen.

「押して」ボタンを押すと、令和までの秒数が表示されます。

HTMLコード

<p>令和まであと…?</p>

<button class="reiwa">押して</button>

<p class="counter"></p>

「今何時でっか?」のテキストを「令和まであと…?」に変更。

JSコード

//オブジェクト取得
const reiwa = document.querySelector('.reiwa');
const counter = document.querySelector('.counter');

//あと何日メソッド
function nanNichi(){

//今の日時
const d1 = new Date();
//ターゲット日時
const d2 = new Date('2019/05/01 00:00'); //令和元年
//時差(ミリ秒)
const d3 = d2 - d1;
// ミリ秒から秒に
const d3_Sec = Math.floor(d3 / 1000);

//テキスト
counter.innerHTML = d3_Sec + "秒!!";
}

//クリックイベント
reiwa.addEventListener('click', nanNichi, false);
  • オブジェク取得は変更なし
  • 関数nanNichi()の中、変数d1は変更なし。
  • 変数d2はターゲット日時のインスタンス。Date( )の引数の中に2019/05/01 00:00を設定
  • 変数d3で時差を出す。d2からd1を引く。
  • 変数d3_Sec、ミリ秒を1000で割って秒に。さらにMath.floor()で小数点を切り捨て。
  • counterには時差(d3)を入れる
  • クリックイベントは変更なし

変わったのは関数nanNichi()の中ですね。Date( )の引数に具体的な日時を入れるとその時間を取得します。そこから現在時刻を引くと時差がわかるわけです。

引き算の結果はミリ秒(0.0001秒)なので1000で割って秒にし、さらに少数を切り捨てています。しかし、秒数だと直感的ではないですね…

算術演算子で秒数を日時に変換する

秒数を「○年○月○日○時○分○秒」という表記になるよう修正。こうなりました。

See the Pen reiwa countdown4 by イイダリョウ (@i_ryo) on CodePen.

「押して」ボタンを押すと表記が具体的な日時になりましたね!どう変わったか。

JSコード

//オブジェクト取得
const reiwa = document.querySelector('.reiwa');
const counter = document.querySelector('.counter');

//あと何日メソッド
function nanNichi(){

//今の日時
const d1 = new Date();
//ターゲット日時
const d2 = new Date('2019/05/01 00:00'); //令和元年
//時差(ミリ秒)
const d3 = d2 - d1;
// ミリ秒から秒に
const d3_Sec = Math.floor(d3 / 1000);

//分、時、日の秒数
const Minute_Sec = 60;
const Hour_Sec = 60 * 60;
const Day_Sec = 60 * 60 * 24;

//あと何日  
const d4_Day = Math.floor(d3_Sec / Day_Sec);

//あと何時間
const d5_Hour = Math.floor(d3_Sec / Hour_Sec  % 24);

//あと何分
const d6_Minute = Math.floor(d3_Sec / Minute_Sec % 60);

//あと何秒
const d7_Sec = Math.floor(d3_Sec % 60);
   
//カウントダウン
counter.innerHTML = d4_Day + "日" + d5_Hour + "時間" + d6_Minute + "分" + d7_Sec + "秒!!";

}

//クリックイベント
reiwa.addEventListener('click', nanNichi, false);
  • 関数nanNichi()の変数d3_Secまでは変更なし。
  • 変数Minute_Secは1分あたりの秒数(60)
  • 変数Hour_Secは1時間あたりの秒数(60×60=360)
  • 変数Day_Sec1日あたりの秒数(60×60×24=8,640)
  • 変数d4_Dayはあと何日:秒数を1日あたりの秒数で割る(以下、少数は切り捨て)
  • 変数d5_Hourはあと何時間:秒数を1日あたりの秒数で割り、さらに24時間(1日)で割った余り
  • 変数d6_Minuteはあと何分:秒数を1時間あたりの秒数で割りさらに60秒(1分)で割った余り
  • 変数d7_Secはあと何秒:秒数を60秒で割った余り
  • クリックイベントは変更なし

時差の秒数を日時に変更するには算術演算子を使います。特殊なのは%の部分です。これは「剰余」といって割り算をしたあとの余りの数を返します。(例:10÷3の場合は1を返す)

秒数の割り算で85分になった場合は、1時間(60分)で割った余りの25分が表示されます。期待通りの表示になりました!最後にボタンをカウントダウンタイマー化したい。

setTimeout()でカウントダウンタイマーを設定

ボタンによって最新日時は取得しやすくなりましたが、もう一歩進めて、ユーザーの操作なしに最新日時をを常時表示をします。

See the Pen reiwa countdown5 by イイダリョウ (@i_ryo) on CodePen.

ボタンはなくなって「令和まであと…」の下に日時が常に表示されています!!

HTMLコード

<p>令和まであと…?</p>

<p class="counter"></p>

「押して」ボタンをなくしました。

JSコード

//オブジェクト取得
const reiwa = document.querySelector('.reiwa');
const counter = document.querySelector('.counter');

//あと何日メソッド
function nanNichi(){

//今の日時
const d1 = new Date();
//ターゲット日時
const d2 = new Date('2019/05/01 00:00'); //令和元年
//時差(ミリ秒)
const d3 = d2 - d1;
// ミリ秒から秒に
const d3_Sec = Math.floor(d3 / 1000);

//分、時、日の秒数
const Minute_Sec = 60;
const Hour_Sec = 60 * 60;
const Day_Sec = 60 * 60 * 24;

//あと何日  
const d4_Day = Math.floor(d3_Sec / Day_Sec);

//あと何時間
const d5_Hour = Math.floor(d3_Sec / Hour_Sec  % 24);

//あと何分
const d6_Minute = Math.floor(d3_Sec / Minute_Sec % 60);

//あと何秒
const d7_Sec = Math.floor(d3_Sec % 60);
   
//カウントダウン
counter.innerHTML = d4_Day + "日" + d5_Hour + "時間" + d6_Minute + "分" + d7_Sec + "秒!!";

//1秒ごとに実行
setTimeout(nanNichi, 1000);
}

//関数実行
nanNichi();
  • 関数nanNichi()の中、最後にsetTimeout()でタイマーを設定。nanNichi関数1秒(1000ミリ秒)ごとに実行
  • ボタンをなくしたのでクリックイベントは削除し、nanNichi()関数実行を書く(ページ読み込みと同時に実行)

これで完成です。平成のうちに間に合った〜。さあこれで令和に向けてカウントダウン!!

※2019/05/01追記
1日経って令和になりました。タイマーを見ると数値がマイナス表記になり、時間と分が1つずつ多い。業務で使用するには時間になった後の表記を変えるif文を書いた方がいいことがわかった。

まとめ

まとめです。

f:id:idr_zz:20190430173522j:plain

  • Dateオブジェクトで現在日時を取得する(表記が欧米風)
  • .getFullYear()などのメソッドで日時を個別に取得(ページを読み込まないと更新されない)
  • クリックイベントにして再読み込み(ボタンを押すと現在時刻に更新できる)
  • Date()の中にターゲット日時を入れて時差を出す(表示は秒数)
  • 算術演算子で秒数を日時に変換する(剰余%で余りを出すのがポイント)
  • setTimeout()でカウントダウンタイマーを設定(ボタンなしで常時表示)

DateオブジェクトとsetTimeout()を組み合わせてカウントダウンタイマーを作りました。どちらも用途が多い機能です。他にもいろいろな機能との組み合わせが考えられますので活用していきましょう!それではまた!!


※参考:ネイティブJSやってみたシリーズ
qiita.com